03.06.2013 Views

Turbo Prolog

Turbo Prolog

Turbo Prolog

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!