So I'm trying to figure out some stuff from Prolog, but I'm not sure WHY I'm getting the result that I'm getting. Given this definition:
families(_, Smith, lucy, _, jeff, Smith).
and this query:
?- families(Ford, nancy, Ford, jeff, Smith, White).
Why is this the result?:
Ford = lucy,
Smith = jeff,
White = nancy.
Thank you!
(A note: no need to leave spaces after the opening and before the closing parenthesis. Also, if this is homework, you should say so.)
The definition of families/6
,
families(_, Smith, lucy, _, jeff, Smith).
says:
- Ignore first argument and fourth argument (the underscores);
- Unify the second and the last argument (both arguments referred to by the same variable name, Smith);
- Unify the third argument with the atom
lucy
;
- Unify the fifth argument with the atom
jeff
.
Now your query,
?- families(Ford, nancy, Ford, jeff, Smith, White).
asks:
- Can you unify the first and third argument with the same variable, Ford?
- yes, you can, and now
Ford = lucy
(from 3. in the definition).
- Can the second argument be the atom
nancy
?
- yes, and
White = nancy
(from 2. in the definition)
- Can the fourth argument be the atom
jeff
?
- yes, but this doesn't have any effect (from 1. in the definition)
- Can you unify the fifth argument with the variable Smith?
- yes, and
Smith = jeff
(from 4. in the definition).
This should be clear now, assuming you know how unification works. Important is that variable names in the definition and the query are in different contexts and having the same name means nothing (as in Smith in positions 2 and 6 in the definition and Smith in position 5 in the query).
Altogether this is a convoluted example that uses variable and atom names in an attempt to confuse the human reader. It forces you to pay attention though and can be useful as an example of bad programming style.
As a visual aid to the answer by Boris, we can write the predicate and the query one beside the other,
families( _ , Smith, lucy, _ , jeff , Smith).
?- families( Ford, nancy, Ford, jeff, Smith, White).
Now, Smith
in the definition and Smith
in the query are not the same! Each predicate has its own "namespace" in effect, because predicate's variables are renamed on predicate's use. So we actually have here
families( _ , A , lucy, _ , jeff , A ).
?- families( Ford, nancy, Ford, jeff, Smith, White).
which matches, producing the substitution
_=Ford, A=nancy, lucy=Ford, _=jeff, jeff=Smith, A=White.
i.e.
Ford=lucy, Smith=jeff, White=nancy.
The last one is the consequence of White=A
and A=nancy
. A
itself isn't reported because it is not one of the query's logical variables.