Списки
Для представления списков произвольной длины используется специальная рекурсивная структура “./2” . Первый аргумент - терм любого вида; второй аргумент - другая структура “./2” или пустой список, обозначаемый [].
Список из одного элемента - атома a:
.(a,[]),
список из трех элементов a, b и c:
.(a,.(b,.(c,[]))).
Эквивалентная форма представления списков:
[a]
[a,b,c]
[[a,b],[a,b,c],[]]
Представление списков произвольной длины ³ 2:
.(one,.(two,X))
[one,two|X]
Символ "|" разделяет список на две части: начало списка и остаток списка; если начало списка состоит из одного элемента, то части называются голова списка и хвост списка. Если H - голова списка, а T - хвост, то список представляется термом [H|T].
Примеры унификации списков:
Список 1 | Список 2 | Конкретизация переменных | |||
[X,Y,Z] | [‘орел’,’курица’,’утка’] | X=‘орел’, Y=‘ курица’,
Z= ‘утка’ | |||
[7] | [X|Y] | X=7, Y=[] | |||
[1,2,3,4] | [X,Y|Z] | X=1, Y=2, Z=[3,4] | |||
[1,2] | [3|X] | нет унификации | |||
[1|[2]] | [X|Y] | X=1, Y=[2] |
Некоторые предикаты со списками
member(?Elem, ?List)
Отношение выполнено, когда Elem может быть унифицирован с одним из членов списка List.
member(A, [A|B]).
member(A, [B|C]) :-
member(A, C).
?- member(1,[3,4,1]).
Yes
?- member(1,[[1]]).
No
?- member(X,[a,b,[c,d],[]]).
X = a ;
X = b ;
X = [c,d] ;
X = [] ;
No
?- member(5,[X,Y|Z]).
X = 5
Y = G772
Z = G776 ;
X = G760
Y = 5
Z = G776 ;
X = G760
Y = G772
Z = [5|G1240]
Yes
append(?List1, ?List2, ?List3)
Отношение выполнено, когда список List3 унифицируется с конкатенацией списков List1 и List2.
append([], A, A).
append([A|B], C, [A|D]) :-
append(B, C, D).
?- append([a,b],[c,d],[a,b,c,d]).
Yes
?- append([a,b],[c,d],[a,b,a,c,d]).
No
?- append([8,7,6],[1,2,3],L).
L = [8,7,6,1,2,3]
Yes
Предикат append позволяет также расщеплять список на два подсписка.
?- append(L1,L2,[a,b,c]).
L2 = [a,b,c]
L1 = [] ;
L2 = [b,c]
L1 = [a] ;
L2 = [c]
L1 = [a,b] ;
L2 = []
L1 = [a,b,c] ;
No
?- append(L1,[a,b],[c,a,b]).
L1 = [c]
Yes
?- append(L1,[a,b],L3).
L3 = [a,b]
L1 = [] ;
L3 = [G1292,a,b]
L1 = [G1292]
Yes
?- append(L1,L2,L3).
L2 = G740
L3 = G740
L1 = [] ;
L2 = G740
L3 = [G1112|G740]
L1 = [G1112]
Yes
Новое определение member
member1(X,L):-
append(_,[X|_],L).
Это определение имеет очевидный декларативный смысл.
Добавить элемент спереди к списку
‘добавить’(X,L,[X|L]).
select(?List1, ?Elem, ?List2)
Селектирует элемент списка List1, который унифицируется с Elem. List2 унифицируется со списком, получаемым из List1 после удаления выбранного элемента. Обычно используется шаблон +List1, -Elem, -List2, но может также использоваться для вставки элемента в список по шаблону
-List1, +Elem, +List2.
select([A|B], A, B).
select([A|B], C, [A|D]) :-
select(B, C, D).
?- select([a,b,c],X,Y).
X = a
Y = [b,c] ;
X = b
Y = [a,c] ;
X = c
Y = [a,b] ;
No
?- select([a,b,c],b,X).
X = [a,c]
Yes
?- select(X,a,[b,c,d]).
X = [a,b,c,d] ;
X = [b,a,c,d] ;
X = [b,c,a,d] ;
X = [b,c,d,a] ;
No
Еще один вариант member
member2(X,L):-
select(L,X,_).
delete(+List1, ?Elem, ?List2)
Удаляет все элементы списка List1, что унифицируются с Elem и одновременно унифицирует результат с List2.
?- delete([a,b,a,c,a],a,X).
X = [b,c] ;
No