Looking at reverse/2 and its related predicates, i was wondering why it is reverse/4 in the SWI Prolog library in spite of reverse/3 in Learning Prolog Now … anybody to explain it ?
Using lpn:
accRev([H|T],A,R):- accRev(T,[H|A],R).
accRev([],A,A).
rev(L,R):- accRev(L,[],R).
?- rev(X, [a,b]).
ERROR: Stack limit (1.0Gb) exceeded
ERROR: Stack sizes: local: 0.7Gb, global: 0.2Gb, trail: 34.1Mb
While
?- reverse(X, [a,b]).
X = [b, a] ;
false.
Thanks. Always simpler with a concrete example moreover i don’t know why i didn’t see at first the mentions by LogicalCaptain. I reopened that subject as i found it interesting to understand why such a difference in code matters.
It is tail-recursive, thus can be optimized into a loop by the compiler. Instead of keeping the elements on a stack with the depth of the list, to be collected and prepended to result list when coming back from the recursion, it constructs the result as a structure on the heap:
[X|Rs]
to be unified with the result variable Ys in the base case.*The Bound is there to make the call symmetric, and make sure the call fails early when both lists are of unequal length or makes sure the list are of equal length when there is one open list among the arguments. But I can’t get my head around all of the special cases covered by it. Alien technology!