Reputation: 13
I have to say that there is a similar quetion Sum of elements in list in Prolog needs little explanation, but still makes me confused.
Here is the following solution which needs some explanation.
sum([H],H).
sum([H|T],R):-sum(T,P),R is H + P.
Lets say we do sum([1,2,3],R).
sum([1,2,3],R)
sum([2,3],<unknown-1>)
sum([3],<unknown-2>)
so where it will fulfill the fact sum([H],H) ? I do write the variable in sum([H],H), the only output for this case is 3, which means that in the unknown-2 here is 3, why?
Just a beginner in prolog and any answers will be great appreciate.
Upvotes: 1
Views: 157
Reputation: 1021
sumList([],0).
sumList([X|Tail],Sum):-
sumList(Tail,Sum1),
Sum is Sum1+X.
Upvotes: 0
Reputation:
The short answer: unification.
When, within the scope of a predicate clause, a variable name occurs more than once, all occurrences will be unified with each other. The predicate for unification is =/2
, and is declared as operator, so =(A, A)
and A = A
mean the same. More importantly, this:
=(Term, Term).
is the definition of =/2
(see the documentation!)
In your example, you have a clause that says:
sum([H], H).
This means:
When the first argument of
sum/2
is a list with exactly one element, the second argument ofsum/2
is that element.
Because term unification is such a fundamental operation in Prolog, usually, it is not spelled out explicitly, as for example:
When the first argument of
sum/2
is a list with exactly one element, that element and the second argument ofsum/2
are unified with each other.
At least in the SWI-Prolog documentation, if unification is involved, it is usually described with "X is Y" instead of "X and Y are unified". See, for example, the documentation of min_member/2
:
min_member(
Min
,List
).True when
Min
is the smallest member in the standard order of terms. Fails ifList
is empty.
It doesn't explicitly tell you that unification is used, and from that, the following behavior follows:
?- min_member(3, [1,2,X]).
X = 3.
I once asked a question about this because I found it too confusing.
By the way, with your current definition of sum/2
, you can also get surprises because of the way that unification works. Look:
?- sum([1.5, 2.5], Sum).
Sum = 4.0 ; % unnecessary choice point but at least correct
false.
?- sum([1.5, 2.5], 4).
false. % Oops!
The SWI-Prolog library implementation suffers from the same problem:
?- sum_list([1.5, 2.5], Sum).
Sum = 4.0. % no choice point, at least
?- sum_list([1.5, 2.5], 4).
false. % Oops!
The work-around is to leave the second argument a free variable at first, and then use =:=/2
, which does arithmetic comparison of numbers:
?- sum_list([1.5, 2.5], Sum), Sum =:= 4.
Sum = 4.0.
You can do this with your definition of sum/2
as well.
Upvotes: 5