I\'m having trouble understanding the following factorial program
fact1(0,Result) :-
Result is 1.
fact1(N,Result) :-
N > 0,
N1 is N-1,
fac
Generally speaking, @m09's answer is basically right about the importance of tail-recursion.
For big N
, calculating the product differently wins! Think "binary tree", not "linear list"...
Let's try both ways and compare the runtimes. First, @m09's factorial/2
:
?- time((factorial(100000,_),false)). % 200,004 inferences, 1.606 CPU in 1.606 seconds (100% CPU, 124513 Lips) false.
Next, we do it tree-style—using meta-predicate reduce/3 together with lambda expressions:
?- time((numlist(1,100000,Xs),reduce(\X^Y^XY^(XY is X*Y),Xs,_),false)). % 1,300,042 inferences, 0.264 CPU in 0.264 seconds (100% CPU, 4922402 Lips) false.
Last, let's define and use dedicated auxiliary predicate x_y_product/3
:
x_y_product(X, Y, XY) :- XY is X*Y.
What's to gain? Let's ask the stopwatch!
?- time((numlist(1,100000,Xs),reduce(x_y_product,Xs,_),false)). % 500,050 inferences, 0.094 CPU in 0.094 seconds (100% CPU, 5325635 Lips) false.