/* CS 1621 Fall 2005 Prolog Example to demonstrate simple recursion */ /* Predicate to sum numbers from 1 to N. It is assumed that the question */ /* will instantiate N, and RESULT will be instantiated when the goal is */ /* satisfied. However, if both values are instantiated when the question */ /* is asked, the predicate will have a boolean effect. */ sum_to(1,1). sum_to(N, RESULT) :- N > 1, /* test to see if N > 1. */ N1 is N - 1, /* Note that a NEW variable is needed*/ sum_to(N1, M), /* to store the value N - 1. Using */ RESULT is N + M. /* "N is N - 1" would fail, since N */ /* is already instantiated. Simply */ /* making the recursive call with N - 1, as in "sum_to(N-1, M)" */ /* (a common way of doing it in languages like C++ and Java) would*/ /* also not work, since N-1 is not actually evaluated without the*/ /* "is" predicate */ b_sum_to(1,1). b_sum_to(N,RESULT) :- N1 is N - 1 , /* same sum_to predicate as above */ b_sum_to(N1,M) , /* but now without the check for */ RESULT is N + M. /* N > 0. Since the base case fact*/ /* is given prior to the recursive */ /* rule, given normal circumstances, this version will work*/ /* just as the first version did. However, if N is given */ /* an initial value less than one, or if the user elects to*/ /* have it backtrack (by hitting ";"), this version will go*/ /* into an infinite recursive chain. */ /* The two predicates above are somewhat "traditional" recursive algorithms that resemble those used in imperative languages. However, the true power of Prolog can be seen in the version below. This version can be used in the following ways: 1) Both arguments are instantiated -- it will verify if the question is true. However, if the arguments don't "match" it will recurse infinitely. 2) First argument instantiated and the second not -- if it succeeds it will instantiate the other result and show its value. In this case backtracking will not work -- it will recurse infinitely. 3) Second argument instantiate and first not. In this case it will succeed and instantiate the first argument as long as the argument provided is a valid sum. If it is not it will have an infinite recursive loop. 4) Neither argument instantiated -- in this case the result will "count up" all values of the variables that will satisfy the question. Each time it backtracks it returns the next highest answer. The infinite recursive loops can occur with this predicate due to left recursion. The problem is similar to that with recursive descent parsers, as we discussed previously. */ c_sum_to(1,1). c_sum_to(N, RESULT) :- c_sum_to(A,B), N is A+1, RESULT is B+N.