Advanced Tracing

We demonstrate advanced tracing of the default debugger for a simple example. Determinism and non-determinism can be combined in ordinary execution and they are an important build-ing block of Prolog search. We use the predicate from the previous sections and try a search problem. The first attempt goes wrong:

?- nodebug.
?- rev(X, [3,4]).
X = [4,3] ;
Error: Execution aborted since memory threshold exceeded.

By tracing the offending execution, we can get an idea why the search went astray. We need to use the debug/0 debugger directive to let the debugger accumulate tracing information. We can then switch to tracing after the first answer substitution and we will see all redo ports so far. We will also see how a call ports build-up:

?- debug.
?- rev(X, [3,4]).
X = [4,3] trace.
X = [4,3] ;
    0 Redo rev([4,3], [3,4]) ?
    1 Redo rev([4,3], [], [3,4]) ?
    2 Redo rev([3], [4], [3,4]) ?
    3 Redo rev([], [3,4], [3,4]) ?
    4 Call rev(_A, [_B,_C,_D], [3,4]) ?
    5 Call rev(_E, [_F,_B,_C,_D], [3,4]) ?
    6 Call rev(_G, [_H,_F,_B,_C,_D], [3,4]) ?
    7 Call rev(_I, [_J,_H,_F,_B,_C,_D], [3,4]) ?
    8 Call rev(_K, [_L,_J,_H,_F,_B,_C,_D], [3,4]) ? abort.

We used the abort/0 debugger directive to abort the offending execution, so that we do not need to reach the memory threshold to return to the top-level. The lesson here is that simple predicates need not be bi-directional and always work for all call patterns. How to solve this problem depends on the actual requirements. Here is a simple solution with length/2:

?- nodebug.
?- use_module(library(basic/lists)).
% 1 consults and 0 unloads in 16 ms.
?- length(X, 2), rev(X, [3,4]).
X = [4,3]

The above example gave a scenario to use the debug/0 debugger directive. The above exam-ple also showed valuable use cases of debugger directives either after an answer substitution without a further prompt "?-" or after a debugger prompt "?". For more information on debugger directives, see the next chapter.