Условия цепочки
Если я правильно понял, вы хотите создать список людей, которые дружат с paul
, peter
и connor
. Мы можем сделать это, «построив» цель, которая направлена на удовлетворение трех условий:
findall(F, <b>(friend(F, paul), friend(F, peter), friend(F, conner))</b>, L).
или другое сочетание условий. Затем они дают:
?- findall(F, (friend(F, paul)), L).
L = [mary, chris, tyler].
?- findall(F, (friend(F, paul), friend(F, peter)), L).
L = [mary, chris].
?- findall(F, (friend(F, paul), friend(F, peter), friend(F, conner)), L).
L = [chris].
Отфильтруйте существующий список с помощью member/2
в цели
Или мы также можем использовать два вызова и использовать member/2
для «эмуляции» пересечения, например:
findall(F, friend(F, paul), L1),
findall(F, <b>(member(F, L1),</b> friend(F, peter)<b>)</b>, L2).
здесь мы, таким образом, используем member/2
таким образом, что F2
принимает значения только от L1
(результат начального findall/3
), но я думаю, что первый способ чище и более самоочевиден: мы хотим после всех список F
с друзьями paul
, peter
и conner
.
Использование maplist/2
для получения людей, которые дружат со всеми в списке
Мы также можем найти людей, которые дружат со списком людей, используя maplist/2
здесь:
findall(F, <b>maplist(friend(F),</b> [paul, peter, conner]<b>)</b>, L).
Постобработка с пересечением
Мы также можем сделать два отдельных вызова findall/3
, а затем рассчитать пересечение:
findall(F, friend(F, paul), L1),
findall(F, friend(F, paul), L2),
intersection(L1, L2, M).
Здесь M
будет содержать элементы, которые находятся как в L1
, так и L2
. Но потенциальная проблема здесь заключается в том, что второй предикат может генерировать много результатов, которые были бы невозможны, если мы отфильтровали значения первого предиката.