Reputation: 61
I want to append a list to a list.
foo([a,b,c]).
goo([d,e,f]).
hi(X):-append(foo(X),goo(X)).
I want to get the result as shown below. But I realized I cannot execute foo(X)
and goo(X)
.
?- hi(X).
|: [a,b,c,d,e,f].
Upvotes: 2
Views: 5216
Reputation: 477607
A common misconception about Prolog is that it has no functions: it only has predicates. A predicate has no input or output, it unifies variables with which it is called. As a result, a predicate can be mutlidirectional.
Another misconception about prolog is that if you call:
append(foo(X), goo(Y)).
that Prolog will see foo(x)
and goo(Y)
as predicate calls. It does not: in this case foo(X)
and goo(Y)
are terms. Terms with a functor (not a predicate) and terms. So here foo(X)
is a term with the functor foo/1
with term X
as first (and only) parameter.
You can however call predicates, by writing these in the body of another predicate.
Here for instance you probably want:
hi(X) :-
foo(A),
goo(B),
append(A, B, X).
So how does this works? If we call hi(X)
, then Prolog will look in the source code for whether there is a predicate defined by that name. If there is, it will aim to execute the clauses of the predicate top to bottom. Here there is only one clause for hi/1
, the one we have just written. So now Prolog will start executing the body of that clause.
We now see that the first item in the body is foo(A)
(notice the A
, not X
). SO now Prolog will again look for a clause for the foo/1
predicate. And there is one in your question. foo([a,b,c])
. That means that Prolog will now perform unification. It will unify our variable A
with the fact. So after calling the foo/1
predicate, now A = [a,b,c]
. We do the same with goo(B)
: after calling it, B = [d,e,f]
.
Finally we call append(A, B, X).
. Now append/3
is a builtin predicate that appends the lists in the two first parameters to the third parameter (but it can be used multidirectional). After the call, X
will thus be unified as [a,b,c,d,e,f]
. Since it is the end of the predicate call, Prolog will report that X = [a,b,c,d,e,f]
.
Are we done now? No! Another vital aspect of Prolog is that it has backtracking syntactically for free. That means that for each predicate call we have done (foo(A)
, goo(B)
, and append(C)
), there can still be clauses in which we are interested. So conceptually the Prolog interpreter will look for more answers. But here we are lucky that foo/1
and goo/1
have only one definition. Note that most Prolog interpreters will not have to do this backtracking here, since they will do some bookkeeping such that it is known in advance whether we should try to backtrack.
Upvotes: 1
Reputation: 5021
It is also possible to write your own appending predicate, it might help you to more fully understand Prolog:
append_list([],L, L).
append_list([Head|Tail], List2, [Head|List]):-
append_list(Tail, List2, List).
It takes the first element of your first list and plugs it into the resultant list, then recursively calls itself without the first element of the list meaning it will move onto the second element. The base predicate is append_list([], L, L).
this says: when the first list is empty return the resultant list.
Plugging in your values
append_list([a,b,c],[d,e,f],X).
Will return X = [a, b, c, d, e, f]
Upvotes: 1