Вычисление факториала:
.f(0)=1 f(n+1)=(n+1)*f(n)
.predikrtes fak(integer, real)
.clauses
fak(0,1):-!. /* 0!=1 */
fak(N, Fak):-
N>0, /*только для целых положит*/
N1=N-1,
.fak(N1,Fak1), /*опред.(n-1)! */
Fak=N*fak1. /*f(n)=n*f(n-1) */
Goal
.fak(2,X), write(X). /* 2! */
goal
|
|
|
|
(3) fak(2,Fak)
(4) N>0
|
|
|
|
|
(9) N>0
|
|
|
|
|
|
| |||||
|
|
(15).write(X)
2.7 Обработка списков
Список – это упорядоченная элементов, причем элементами могут быть любые термы, включая другие списки.
Пустой список- [ ]
Непустые списки имеют-голову и хвост. Они являются компонентами функтора, обозначаемого точкой ”.”.Например список из одного элемента а представляется так:
.(а,[])
где а-голова и []-хвост. Список элементов a,b, и c имеет вид:
.(а,.(b,.(c,[]))).
То есть, за элементом a следует b, который в свою очередь является головой списка .(b,.(c,[])).
Драгим видом записи списка будет:
._._._[].
На ТП такой список представляется так:
[a,b,c]
где a-голова, b,c-хвост списка, который и сам является списком.
Например, информация о некоторых семьях может выглядеть как предикат со следующей структурой:
.семья(фамилия, имя_отца, имя_матери, [имена детей] ).
Семья(Иванов,Иван,Людмила,[Антон,Наташа,Юрий] ).
В этом случае количество детей не имеет значение, а количество аргументов предиката семья всегда одинаково. Поэтому, если записать целевое утверждение:
семья(X,Y,Z,Дети).
То переменные конкретизируются так:
X=”Иванов” Y=”Иван” Z=”Людмила”
Дети=[“Антон”,”Наташа”,”Юрий”]
На ТП есть специальная форма представления списка
[X|Y].
Если такой спосок сопоставляется с другим списком, то X конкретизируется головой, а Y- хвостом того списка, например:
.семья(X,Y,Z,[Det1|Deti]),
то переменные конкретизируются так:
X=”Иванов” Y=”Иван” Z=”Людмила”
Det1=”Антон” Deti=[”Наташа”,”Юрий”].
Например, наити семью, где имеется ребенок с именем Алекс.
/* set femili */
trace
domains
detlist= person*
person= string
predicates
member(person,detlist)
semja(person,person,person,detlist)
clauses
member(X,[X|_]).
member(X,[_|Y]):-member(X,Y).
semja("Ivanov","Ivan","Ljda",["Anton","Nata","Jri"]).
semja("Sevs","Piter","Vera",[]).
semja("Pospelov","Serg","Ira",["Aleks","Tanj"]).
goal
makewindow(1,121,0,"",12,40,13,40),
semja(F,I1,I2,Det),member("Aleks",Det),
write("Aleks ",F),nl,
write("ОТЕЦ=",I1," МАТЬ=",I2).
При этом предикат member проверяет принадлежность элемента к списку:
Первый дизъюнкт предиката member означает, что искомый элемент находится в голове списка. Если это не так, то выбирается второй дизъюнкт, который отделяет хвост от головы списка и проверяет, находится ли искомый элемент в хвосту. Это происходит рекурсивно до тех пор, пока либо не найдено, что у остатка списка голова является искомым элементом (удача), либо не окажется, что после отделения хваста от головы остался пустой список([]), который уже не расщепляется на голову и хвост (неудача).