PrologEZ
Data & computation ยท Lesson 17 of 43

Lists

The workhorse data structure: [Head|Tail] patterns and the standard library.

A list is a sequence of terms in square brackets: [a, b, c]. The empty list is []. Internally a list is either empty or a head and a tail (itself a list), and Prolog's pattern [H|T] splits it:

?- [H|T] = [a, b, c]
?- [A, B|Rest] = [1, 2, 3, 4]
?- [X] = [a]
?- [_|_] = []

Lists can hold anything, including lists: [1, [a, b], foo(x)].

The essentials

Most list work uses ready-made predicates from the standard library:

?- member(X, [a, b, c])
?- member(b, [a, b, c])
?- length([a, b, c], N)
?- nth0(1, [a, b, c], X), nth1(1, [a, b, c], Y)
?- last([1, 2, 3], X)
?- reverse([1, 2, 3], R)
?- sum_list([1, 2, 3], S), max_list([4, 9, 2], M)
?- msort([c, a, b, a], L), sort([c, a, b, a], S)
?- sort(0, @>=, [3, 1, 2, 3], L)

sort/2 removes duplicates; msort/2 keeps them.

append/3: a relation, not a function

append(A, B, C) means "C is A followed by B". Because it's a relation, it runs in every direction:

?- append([1, 2], [3, 4], L)
?- append(X, [3, 4], [1, 2, 3, 4])
?- append(Before, [c|After], [a, b, c, d, e])
?- append(X, Y, [1, 2, 3])

That last query enumerates every way to split a list in two. You will see this "run it backwards" trick throughout Prolog.

Building and filtering

length/2 can also generate lists; numlist/3 makes ranges; exclude/3, include/3 and maplist/3 (covered in the higher-order lesson) transform them.

?- length(L, 3)
?- numlist(1, 10, L), include([X]>>(X mod 2 =:= 0), L, Evens)
?- delete([a, b, a, c], a, L), subtract([1, 2, 3, 4], [2, 4], S)
?- list_to_set([a, b, a, c, b], S)
?- sumlist([1, 2], S), nextto(X, Y, [1, 2, 3])

Exercise: Swap the first two

Write swap_first_two(List, Swapped) so that the first two elements of the list trade places and the rest is unchanged. Lists with fewer than two elements have no solution.