To understand what happens, you must see Prolog as a theorem solver: when you give Prolog the query ?- copyList([1, 2, 3], L).
, you're essentially asking Prolog to prove that copyList([1, 2, 3], L)
is true.
Prolog will therefore try to prove it. At its disposal, it has two clauses:
copyList([], []).
copyList([H|T], [H|R]):-
copyList(T, R).
As it is the first that it encounters, Prolog wil try to prove that copyList([1, 2, 3], L)
is true by using the clause copyList([], [])
.
To do so, and since the clause has no body (nothing after :-
), it would just have to unify the arguments of your query with the arguments of the clause (unify [1, 2, 3]
with []
and L
with []
). While it is easy to unify L5
with []
(with the unification L5 = []
), it is impossible to unify [1, 2, 3]
with []
. Therefore Prolog has failed to prove your query by using the first clause at its disposal. It must then try to use the second.
Once again it will unify the query arguments with the clause arguments to see if the clause is applicable: here it can do so, with the unifications H = 1, T = [2, 3], L = [H|R]
. Now it has to see if the conditions listed after :-
are respected, so it has to prove copyList(T, R)
. The exact same thing goes on twice, until it finds itself trying to prove copyList([], R)
. There, the first clause is applicable, and its job is over.
You can sum up the execution with a drawing as follows:
copyList([1, 2, 3], L).
|
| try to use clause number 1, doesn't unify with arguments.
| use clause number 2 and L = [1|R]
|
` copyList([2, 3], R).
|
| try to use clause number 1, doesn't unify with arguments.
| use clause number 2 and R = [2|R2]
|
` copyList([3], R2).
|
| try to use clause number 1, doesn't unify with arguments.
| use clause number 2 and R2 = [3|R3]
|
` copyList([], R3).
|
| use clause number 1 and R3 = []. One solution found
| try to use clause number 2, doesn't unify with arguments.
| No more possibilities to explore, execution over.
Now that the execution is over, we can see what the original L
is by following the chain of unifications:
L = [1|R]
R = [2|R2]
R2 = [3|R3]
R3 = []
R2 = [3]
R = [2, 3]
L = [1, 2, 3]
Thanks to Will Ness for his original idea on how to explain the final value of a variable.