Prolog communicates the results of computations by binding variables to terms. Variables can start out unbound, i.e., not bound to any value, and can become bound during a computation by unification.
To some extent you already know this. After all, when you write a query like
?- listmulti([2,1],[3,5],Result).
you do not specify a value for Result
-- it is unbound. But when you run the query, Prolog will bind Result
to a term and tell you what it is:
Result = [6, 5].
We can visualize this by printing the value of Result
before and after it is bound by calling listmulti
:
?- write('before the query, Result is: '), write(Result), nl,
| listmulti([2,1], [3,5], Result),
| write('after the query, Result is: '), write(Result), nl.
before the query, Result is: _G1699
after the query, Result is: [6,5]
Result = [6, 5].
In the beginning, Result
is just some unbound variable, which is shown as _G1699
in this case. (Different variables have different numbers so you can distinguish them.) After the query is run, that same variable is now bound to the list [6, 5]
.
This is also what the tracer was telling you, although it takes some practice to read its output:
Call:listmulti([1], [5], _6268)
...
Exit:listmulti([1], [5], [5])
This is a pair of states just before and just after executing listmulti([1], [5], Spare)
. The current instance of Spare
is unbound before the call and is bound to [5]
afterwards, as listmulti
computed the element-wise product of the lists [1]
and [5]
.
Now consider the following version of your predicate:
listmulti([],[],[]).
listmulti([H1|B1], [H2|B2], AllResults) :-
listmulti(B1,B2, ResultsForTheTailsOfTheLists),
Result is H1 * H2,
AllResults = [Result | ResultsForTheTailsOfTheLists].
When you call this with two lists of numbers in the first two arguments, operationally this will decompose those lists into their heads and tails, and compute the element-wise product of the tails. The result of this is a list of ResultsForTheTailsOfTheLists
. The product of the heads is computed as Result
. And then the results for the complete lists is just the list containing Result
followed by all of the ResultsForTheTailsOfTheLists
. Is this clearer?
The final twist is that in Prolog you can create lists and other data structures before you know what you will put in them. You can construct a list like this:
?- Head = a, Tail = [b, c], List = [Head | Tail].
Head = a,
Tail = [b, c],
List = [a, b, c].
but you can also construct the list first and only then bind its head and tail:
?- List = [Head | Tail], Head = a, Tail = [b, c].
List = [a, b, c],
Head = a,
Tail = [b, c].
And this is what is going on in your original definition: In the head, once you know that you are looking at two lists of numbers, you know that the result will be of the form [HeadResult | TailResults]
. Having this term in the clause head builds it right away. Only later do you compute HeadResult
and the TailResults
through a recursive call. Overall this gives you a complete list.
listmulti([H1|B1],[H2|B2],Result)
easily. Why would it be easier to writelistmulti([H1|B1],[H2|B2],[Result | Spaere])
? Are you referring to the query, or your predicate? – lurker_
is the only anonymous variable. I misspoke in my last comment. But other variables starting with_
, such as_5956
, may be an internally generated variable name. Or you can use_X
for example if you want a named variable but don't care if it's singleton but_X
used anywhere else in the same predicate is the same variable. Whereas_
in multiple places is considered different. – lurker