Basic syntax
Lists in prolog are treated as having two parts: the head, or front, element of the list
and the tail of the list, which is a list of all the remaining elements (i.e. not including
the head element).
Lists can be described in one of two ways,
[10, -1, 8, 20]
[ HeadElem | TailList ]
[ 3, 'foo', [ x, [ y ] ], 17 ]
Unification and Lists
If we try and unify two lists, or a list with a variable, the prolog
engine will attempt to unify the list components appropriately. For example
[ X | Y ] = [ 1, 2, 3] % unifies X with 1 and Y with [2, 3]
[ X, Y ] = [ 1, 2, 3] % fails since we have only 2 elements on the LHS
Remember that such unifications are taking place "behind the scenes"
when we attempt queries such
as foo(A). and the fact/rule database includes items such as
foo([X,Y]).
List functions
Some of the built-in list functions include:
list(List), length(List,Length), min_list(List, Elem),
max_list(List, Elem), append(List1, List2, Result), member(Elem,List),
delete(List, Elem, Result), last(List,Elem),
reverse(List, Result), permutation(List, PermutedList),
nth0(Position, List, Elem), length(List, Size), sort(List, Result)
Recursive operations
As with most aspects of prolog, recursive manipulation of lists is commonplace.
Consider the example below, which tests if an element is a member of a list.
% member(X, L) is supposed to succeed if X is an element of list L % if X matches the front element of a list then X is in the list % (note that we don't care what the rest of the list looks like) member(X, [X | _]). % if we get here, we know X didn't match the head element, so we'll % ignore the head element and see if X matches something in the tail member(X, [_|Tail]) :- member(X, Tail).
This is most commonly done with lists, but there are certainly other options.
The example below shows a representation of objects in a three-dimensional space, representing things using their X, Y, Z coordinates.
% a point is represented by a list of 3 numbers, the X, Y, and Z coordinates
point([ X, Y, Z ]) :- number(X), number(Y), number(Z).
% a line is represented by a list of 2 distinct points
line([ Point1, Point2 ]) :- point(Point1), point(Point2), Point1 \= Point2.
% a plane is represented by a list of 3 distinct points
plane([ Point1, Point2, Point3 ]) :- point(Point1), point(Point2), point(Point3),
Point1 \= Point2, Point1 \= Point2, Point2 \= Point3.
Note that at the user level this allows us to think of components in appropriate
abstract terms, such as plane(P), rather than thinking explicitly
about the underlying representation, which may be something like
[ [1, 2], [17, 0], [-3, -99] ].