I am quite rusty in prolog, but I am not sure why things like this fail:
frack(3).
frack(X) :- frack(X-1).
So, if I evaluate frack(4). from the interactive prompt with the above facts defined, I expect that it should not have to endlessly recurse, since 4-1 = 3. But I get this error in SWI-Prolog:
ERROR: Out of global stack
Try it:
?- 4-1 = 3.
false.
Why? Because 4-1 = -(4, 1)
, which clearly is not a number but a compound term.
To reason about integers in Prolog, use clpfd constraints, for example (using GNU Prolog or B-Prolog):
| ?- 4-1 #= X. X = 3
In SWI-Prolog, the graphical tracer may be useful for you to see what happens:
?- gtrace, frack(4).
For more complex debugging, I recommend failure-slice as shown in false's answer.
Here is the reason for this non-termination. Your query does not terminate, because there is a failure-slice of your program that does not terminate:
?- frack(4).frack(3) :- false. frack(X) :- frack(X-1), false.
You can fix this only by modifying something in the visible part. Three SO-answers suggest to use (is)/2
. But this will not remove non-termination! In fact, using (is)/2
leads to essentially the same fragment:
?- frack(4).frack(3) :- false. frack(X) :- Y is X - 1, frack(Y), false.
At least, frack(4)
now succeeds, but it will loop on backtracking. You have to change something in the visible part, like some test for X
, in order to avoid non-termination. See failure-slice for more.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With