10.3.5.Належність елемента списку.
Припустимо, ми маємо список імен. Нам потрібно написати предикат, який би встановлював належність якогось імені (перший аргумент) вибраному списку імен (другий аргумент ). Нехай цим предикатом буде предикат:
member(name, namelist)
В наступній програмі перша фраза досліджує голову списку. Якщо голова списку співпадає з іменем, яке ми шукаємо , тоді можна зробити заключення, що ім.я належить списку. Тому, що в даному випадку хвіст списку нас не цікавить, він характеризується анонімною змінною. Якщо ж імені немає в голові, тоді його потрібно рекурсивним чином шукати в хвості списку. За це і відповідає друга фраза програми.
domains
namelist = name*
name = symbol
predicates
is_a_member_of(name, namelist)
clauses
is_a_member_of(Name,[Name|_]).
is_a_member_of(Name,[_|Tail]):- is_a_member_of(Name,Tail).
10.4 Використання одного й того ж предикату для вирішення різних задач.
Особливість прологу полягає в тому, що коли ви будуєте предикат для вирішення якоїсь конкретної задачі , то він може використовуватись і для вирішення зовсім інших задач. Продемонструємо це на наступному прикладі. Побудуємо предикат конкатенації двох списків з трьома аргументами:
append(List1,List2,List3)
де List3 є результуючим списком. Використаємо наступний рекурсивний алгоритм.
Якщо перший список пустий, тоді результуючий список буде рівний другому списку (append([],List2,List2)). Інакше, головою третього списку становиться голова першого списку, а хвостом - залишок першого списку і другий список.
Прийдемо до програми:
domains
integerlist = integer*
predicates
append(integerlist, integerlist, integerlist)
clauses
append([], List, List).
append([X|L1], List2, [X|L3]) :-
append(L1, List2, L3).
Якщо ми задамо ціль
goal: append([1,2],[3,4]), тоді отримаємо список [1,2,3,4].
З іншого боку, розглядаючи предикат append з декларативної точки зору, ми визначили відношення між трьома списками. Таке відношення буде вірним і у випадку, коли буде відомий тільки третій список.
Наприклад,
goal: append(L1,L2,[1,2,4] дасть результат
L1 = [], L2 = [1,2,[1,2,4]
l1 = [1], l2 = [2,4]
. . .
Також ви можете використати предикат append, щоб визначити який із списків можна додати до списку [3,4], щоб отримати список [1,2,3,4].
Наприклад, задавши
goal: append[L1,[3,4],[1,2,3,4] матимемо L1 =[1,2]
Предикат append визначає відношення між множинами на вході і виході. Тому відношення може використовуватись різними способами. Задаючи таке відношення, ви можете запитати:
Який вихід відповідає даному входу? або ж
Який вхід відповідає даному виходу?
Статус аргументів даного предикату при виклику, базується на зразку потоку даних. Предикат append може обробляти любий зразок потоку даних.
Але не всі предикати Прологу можуть бути викликані різними зразками потоку даних. Якщо фраза Прологу може оброблятись різними зразками потоку даних, тоді її називають інвертованою фразою. Зазначимо, що використання інвертованих фраз додає потужності вашим предикатам.
