Turbo Prolog
Turbo Prolog
Turbo Prolog
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
Tail recursion elimination is a technique for replacing such forms of recursion with<br />
iteration, and in spite of its name, it is also useful in situations in which there is no direct<br />
recursion or even no recursion at all-just a long chain of procedure calls.<br />
To see how it works, suppose we had defined demopred, which uses member as<br />
follows:<br />
demopred(X,Y):-... ,member(A,B),test(A), ....<br />
When member is first activated, the system must remember that once member has<br />
been successfully evaluated, control must pass to the predicate test. This means that the<br />
address of test must be saved on the stack.<br />
Likewise, for each recursive call of member, the system must remember the address<br />
the member predicate needs to return to after successful evaluation-namely, itself.<br />
Since there are no backtracking points between<br />
member(X,[_IY1)<br />
and the recursive call<br />
member(X,y)<br />
there is no need to stack the address of member several times. It is enough to remember<br />
that on successful termination of member. control should pass to test. This is tail<br />
recursion elimination. Where the system itself cannot eliminate recursion, the programmer<br />
can do a lot to limit its effect (and limit demand on the stack) by adopting a few<br />
rules of thumb about programming style.<br />
Rule I. Use more variables rather than more predicates. This rule is often in direct<br />
conflict with program readability, so a careful matching of objectives is required to<br />
achieve programs that are efficient both in their demands upon relatively cheap<br />
machines and upon relatively expensive human resources.<br />
Thus, if writing a predicate to reverse the elements of a list<br />
reverse(X,y):- reverseL([),X,y).<br />
reverseL(Y,[),Y).<br />
reverseL(XL,[UIX21,Y):- reverseL([UIXL),X2,Y).<br />
makes less demands upon the stack than<br />
reverse ( [ ) , [ 1 ) .<br />
reverse([UIX),Y):-reverse(X,YL),append(YL,[U),Y).<br />
append([l,Y,Y).<br />
append([UIX),Y,[UIZ)):- append(X,y,Z).<br />
which uses the extra predicate append.<br />
Rule 2. When ordering subgoals in a rule, those with the most bound variables should<br />
come ftrst. Thus, if writing a <strong>Turbo</strong> <strong>Prolog</strong> predicate to solve the simultaneous equations<br />
X + L = t;<br />
X + Y = 5<br />
and using a "generate and test" method,<br />
solve(X,y):numb(X),plus(X,l,t;),<br />
numb(y),plus(X,y,S).<br />
146 <strong>Turbo</strong> <strong>Prolog</strong> Owner' s Handbook