My code works for its intended purpose but always gets stuck in a loop at the end giving me an error saying "Stack limit exceeded." My code is below:
by
When you call something like travel(metz, To)
, the last clause of travel/2
will call travel(metz, Z)
with a new variable Z
, which can then call travel(metz, Z2)
with a new variable Z2
, and so on.
This problem is called "left recursion": You have a recursive call that is equivalent to the original goal all the way "to the left" (i.e., at the beginning) of a clause. The solution is to "make some progress" before a recursive call. In this case, you can travel one hop before the recursion:
step(X, Y) :-
byCar(X, Y).
step(X, Y) :-
byTrain(X, Y).
step(X, Y) :-
byPlane(X, Y).
travel(X, Y) :-
step(X, Y).
travel(X, Z) :-
step(X, Y),
travel(Y, Z).
This now terminates:
?- travel(metz, To).
To = frankfurt ;
To = paris ;
To = bangkok ;
To = singapore ;
To = auckland ;
To = hamilton ;
To = raglan ;
To = auckland ;
To = hamilton ;
To = raglan ;
To = losAngeles ;
To = auckland ;
To = hamilton ;
To = raglan ;
false.
As pointed out in a comment by false, you can use a general predicate to capture this kind of closure: Definition of Reflexive Transitive Closure. Alternatively, some Prolog systems provide a feature called "tabling" which you can use to avoid this kind of problem: https://www.swi-prolog.org/pldoc/man?section=tabling-non-termination