I’m working my way through a book, and have been reading about the way Prolog does arithmetic. He explained how =
doesn’t cause evaluation, so 1+2=2+1
will be false, whereas 1+2=:=2+1
would be true.
Along the way, he said that <
would evaluate its arguments.
One of the samples that followed involved writing a predicate to work out the greatest common divisor of two integers. The formula is simple enough…
- if X and Y are equal, then D is X
- if X < Y then D is the GCD of X and Y-X
- if Y < X, do as in 2) but with X and Y reversed
This led me to the following code…
gcd(X, X, X).
gcd(X, Y, D) :-
X < Y,
gcd(X, Y-X, D).
gcd(X, Y, D) :-
Y < X,
gcd(Y, X-Y, D).
However, this always failed.
Using trace/0
(which I’m now beginning to understand), I could see that when it got to the lines with <
, it didn’t evaluate the subtraction…
[trace] 19 ?- gcd(2, 4, D).
Call: (10) gcd(2, 4, _214) ? creep
Call: (11) 2<4 ? creep
Exit: (11) 2<4 ? creep
Call: (11) gcd(2, 4-2, _214) ? creep
Call: (12) 2<4-2 ? creep
Fail: (12) 2<4-2 ? creep
Redo: (11) gcd(2, 4-2, _214) ? creep
Call: (12) 4-2<2 ? creep
Fail: (12) 4-2<2 ? creep
Fail: (11) gcd(2, 4-2, _214) ? creep
Redo: (10) gcd(2, 4, _214) ? creep
Call: (11) 4<2 ? creep
Fail: (11) 4<2 ? creep
Fail: (10) gcd(2, 4, _214) ? creep
false.
If I understand this correctly, then on the 6th line (the first fail
), it’s comparing 2
with 4-2
, which are not the same thing (when not evaluated) and so the comparison fails.
Why doesn’t <
evaluate 4-2
?
Thanks for any help you can give.
P.S. Rewriting the code solved the problem…
gcd(X, X, X).
gcd(X, Y, D) :-
X < Y,
Z is Y-X,
gcd(X, Z, D).
gcd(X, Y, D) :-
Y < X,
Z is X-Y,
gcd(Y, Z, D).
…but I would like to understand why the evaluation wasn’t done, when my book says it should be.
Thanks