The second rule basically says that F
is the factorial of N
if N
is greater than zero and there is a number N1
which is the result of N-1
and F1
is the factorial of N1
and F
is the product of N
and F1
.
Example
Let's say that you want to find the factorial of 3.
-? factorial(3,F).
Prolog puts factorial(3,F)
on the stack of goals and then looks for rules whose head match the first goal. There are two rules for factorial/2
(the fact factorial(0,1)
can be seen as a rule without body), but for the first 0 does not unify with 5 so it cannot be used. The second unifies with N
being instantiated to 5 and Prolog adds the conditions to the stack which becomes:
3 > 0, N1 is 3-1, factorial(N1,F1), F is 3*F1
The first goal is satisfied as 3 is greater than zero. The second one is satisfied by binding N1
to the result of the arithmetic evaluation of 3-1
so the stack of goals is now:
factorial(2,F1), F is 3*F1
Again, Prolog looks for rules that might be used to satisfy factorial(2,F1)
and uses the second one (N
unifies with 2 and F
with F1
and different names are used for the variables) :
2 > 0, N2 is 2-1, factorial(N2,F2), F1 is 2*F2, F is 3*F1
Next, 2 > 0
is true and N2
is unified with the arithmetic result of 2-1
so the stack of goals becomes:
factorial(1,F2), F1 is 2*F2, F is 3*F1
Using again the second rule for factorial/2
:
1 > 0, N3 is 1-1, factorial(N3,F3), F2 is 1*F3, F1 is 2*F2, F is 3*F1
N3
becomes zero (when N3 is 1-1
is being satisfied):
factorial(0,F3), F2 is 1 * F3, F1 is 2*F2, F is 3*F1
At this point, the first rule for factorial/2
can be used to satisfy factorial(0, F3)
, but a choice point is created as there are more rules that can be used. So, factorial(0,F3)
succeeds by instantiating F3
to 1.
F2 is 1 * 1, F1 is 2 * F2, F is 3 * F3
By satisfying all the goals left on the stack, F
becomes 6 and you get your first solution. But, there was a choice point for factorial(0, F3)
. The second rule can be used at that point:
0>0, N4 is 0-1, factorial(N4,F4), F3 is 0*F4, F2 is 1*F3, F1 is 2*F2, F is 3*F3
But 0>0
fails and the execution stops as there where no other choice points to backtrack to.
You can avoid leaving that useless choice point for factorial(0,_)
by using a [green] cut operator.
factorial(0, 1) :- !.