100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

Debugging Prolog Programs

Master Prolog's built-in tracer, spy points, and common failure patterns to systematically debug logic programs.

Practical PrologBeginner8 min readJul 10, 2026
Analogies

Why Debugging Prolog Feels Different

Debugging an imperative program usually means stepping through a sequence of assignments to find the line that produced a wrong value. Debugging Prolog means reasoning about unification and backtracking instead: a bug is typically a wrong answer, a missing answer, or an infinite loop, and the cause is usually an unexpected clause ordering, an unintended variable binding, or a search path that never terminates rather than a single faulty statement.

🏏

Cricket analogy: It is like reviewing why a run-out appeal failed, which is not about 'which line of code executed' but about which unification of foot-to-crease timing did not hold, closer to checking replay angles than a checklist.

The Built-in Tracer: trace/0 and the 4 Ports

Calling trace/0 activates Prolog's box model debugger, which reports every goal invocation through four ports: Call when a goal is first invoked, Exit when it succeeds, Redo when backtracking re-enters it looking for another solution, and Fail when it fails outright. The leash/1 predicate controls which of these ports actually pause execution for interactive inspection, letting you skip noisy ports like Call while still stopping on Fail.

🏏

Cricket analogy: It is like a stump microphone paired with four camera angles, run-up, delivery, impact, and reaction, each capturing a distinct phase of the ball, with the third umpire able to pause on whichever phase matters.

prolog
% Buggy: intended to compute factorial
fact(0, 1).
fact(N, F) :- N > 0, N1 is N - 1, fact(N1, F1), F is N * F1.

?- trace, fact(3, X).
%  Call: (8) fact(3, _1234) ?
%  Call: (9) 3>0 ?
%  Call: (9) _1240 is 3-1 ?
%  ...
%  X = 6.

Spy Points and Selective Tracing

Tracing an entire program port by port is overwhelming once a program grows past a handful of predicates. spy/1 sets a breakpoint on a specific predicate indicator, such as spy(fact/2), so the tracer only activates when that predicate is called, and nospy/1 removes it again. This lets you isolate suspected predicates without wading through unrelated goals firing elsewhere in the program.

🏏

Cricket analogy: It is like placing a fielder specifically at deep midwicket to watch for one batter's favorite shot rather than reviewing footage of the entire innings ball by ball.

Once you have found the issue, call notrace/0 (or nodebug/0) to turn off the debugger quickly without restarting the query, and nospy/1 to clear any breakpoints you set with spy/1 so they don't keep firing on later runs.

Common Bug Patterns

Three patterns account for most Prolog bugs. A singleton variable, one that appears only once in a clause, is almost always a typo, and SWI-Prolog will warn about it at load time. A missing cut lets a predicate that should succeed once backtrack into unwanted alternative solutions on redo. And confusing is/2 with =/2 causes subtle failures: is/2 evaluates its right-hand side as arithmetic and requires it to already be a bound expression, while =/2 merely attempts unification and succeeds on structurally matching terms without evaluating anything.

🏏

Cricket analogy: It is like a scorer typo-ing a player's name once so it never matches their other entries, a singleton that never links back and breaks the season stats, alongside forgetting to declare an innings closed, a missing cut that keeps offering extra overs indefinitely.

Do not reach for cut (!) purely to suppress unwanted extra solutions without understanding why they appear. A cut placed to paper over a symptom can hide a genuine logic error in the rules, and it also makes the predicate less reusable, since it forces one deterministic reading even in contexts where exploring alternatives was legitimate.

  • Prolog bugs are usually wrong answers, missing answers, or infinite loops rather than crashes.
  • trace/0 activates the four-port box model debugger: Call, Exit, Redo, Fail.
  • leash/1 controls which of the four ports pause execution for inspection.
  • spy/1 and nospy/1 let you debug selectively by predicate instead of tracing the whole program.
  • Singleton variable warnings often point to typos in variable names.
  • A missing cut can cause a predicate to backtrack into unwanted extra solutions.
  • Using cut purely to suppress unwanted backtracking can hide logic errors and hurt reusability.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#PrologStudyNotes#DebuggingPrologPrograms#Debugging#Prolog#Programs#Feels#StudyNotes#SkillVeris#ExamPrep