I'm quite new to prolog, and I tried the following:
| ?- append([1],2,R).
R = [1|2]
yes
I have no idea what the notation [1 | 2]
means. Trying to search this was painful, and I couldn't find any thing. I guess this is something like the lisp (1 . 2)
resulted from (cons 1 2)
. Can someone explain/reference to explanations about this?
If it matters to anyone, I'm using GNU-prolog version 1.3.0
The "General" form of
[H|T]
The list notation
[H|T]
is a syntactic sugar for'.'(H,T)
which is the predicate defining the list by head and tail. For example, the list[1,2,3]
could also be written'.'(1,'.'(2,'.'(3,[]))).
(try,X = '.'(1,'.'(2,'.'(3,[]))).
at the prolog prompt).Since you seem familiar with Lisp, then in those terms,
X
is thecar
of the list[X|T]
andT
is thecdr
of the list[X|T]
.append/3
is typically used with list arguments, so to append an atom (calledatom
) to a listL
and result beingR
, you'd do it like this:Or more specifically:
Yields:
R = [1,2]
.In using
append/3
to define an implementation forrev/2
, Clocksin & Mellish, Programming in Prolog, Fifth Edition, on p.157 state, in that context:If you're given a list,
L
, you can retrieve the head (car) and tail (cdr) by unifying it with the[H|T]
form:For example:
You can also pull off as may elements as you wish:
It will fail if you try to do too many:
The
[H|T]
form is handy in list processing predicates, particularly recursive ones:If you were to write a list, say,
[1,2,3]
literally in the[H|T]
form, you'd have any of the following equivalents:The list form
[H|T]
whenT
is an atomIf you have a list
[X|T]
, meansX
is the head of the list, andT
is the tail (usually a list itself). Although Prolog lets you construct such a list in whichT
is an atom, it doesn't seem commonly used, at least not as it is in Lisp. But, yes,[1|2]
is indeed like(1 . 2)
in Lisp. Lisp has some built-in functions which operate on lists of(a . b)
as key-value pairs, etc. Prolog doesn't have any built-ins that take advantage of the[a|b]
structure that I'm aware of. They may have no more advantage over just using[a,b]
. I also have searched for references to the[a|b]
(or[a1,...,an|b]
) form and found one in Clocksin & Mellish, p.53, in reference to an example unifying[white|Q]
with[P|horse]
:The interesting thing is that most of the other built-in Prolog predicates that process a list will actually fail when given the
[a1,...,an|b]
form. For example, in GNU Prolog:SWI Prolog throws an exception:
Similar results occur with other predicates.
maplist
will work on all of the elements of such a list but will ignore the tail atom.append/3
will work as long as the first list does not have an atom as its tail.The question about atom as tail in a list is a very good one. It seems Prolog allows it (you can unify
X=[1|2].
for example), and theappend/3
built-in handles it (perhaps inadvertently due to its simple design). I can be used as a valid form for data,[a1,...,an|b]
and can be unified with forms that look like it. But most of the built-ins don't seem to consciously handle it properly. It also isn't acting as a generic 2-argument functor (attempt to unifyX=3|4.
would fail).So, the form
[a1,...,an|b]
(whereb
is an atom) is a valid Prolog data structure, but it's behavior as a list must be handled carefully since most predicates assume that the tail of a list is a list, and that the "final" tail is the empty list,[]
. So it can be legitimately used if desired, but with caution (as C&M indicate).