заказ реализация
Вы можете решить эту проблему, например, с помощью member/2
и аккумулятор:
people(L) :-
people([],L).
people(L,[X|R]) :-
person(X),
\+member(X,L),
people([X|L],R).
people(L,[]) :-
\+ (person(X),\+ member(X,L)).
Или, если вы знаете, как работать с сократить (!
), вы можете использовать @CapelliC's version :
people(L) :-
people([],L).
people(L,[X|R]) :-
person(X),
\+member(X,L),
!,
people([X|L],R).
people(L,L).
Поэтому каждый раз, когда вы ищете person/1
X
, так что он не является членом L
. Если вы больше не можете найти такого человека, выбирается последнее предложение. В этом случае пустой список []
распространяется в обратном направлении, а для каждого элемента в стеке вызовов добавляется конкретный X
.
Использование findall/3
предопределённые
Пролога варианты, которые следуют стандартам ISO, однако, имеют в встроено findall/3
:
findall(+Template, :Goal, -Bag)
Вы можете использовать его следующим образом:
Template
функтор (это может быть переменная) данных, которые вы хотите получить, здесь X
;
Goal
- предикат (или список предикатов и т. Д.), Которые должны быть выполнены. Пролог, внутренне, вызовет Goal
; и
Bag
- выход: список результатов.
Если вы используете это как:
people(L) :-
findall(X,person(X),L).
он будет генерировать список всех person/1
с:
?- findall(X,person(X),L).
L = [sam, tom, holly].
Есть другие высшие предикаты порядка, которые гарантируют уникальность и т.д.
Семантические различия
Обратите внимание, что findall/3
и наш собственный подход people/1
не являются семантически эквивалентными.Действительно, если ваша база данных содержит человека дважды, он будет дважды в сумке findall/3
. Кроме того, наш собственный people/1
будет перечислять списки в любом возможном порядке.
@CommuSoft показывает вам, как это сделать. Причина, почему то, что у вас есть, не работает, потому что Prolog начинается с начала фактов, когда вводится новый запрос предложения предиката. Таким образом, с каждым рекурсивным призывом к «людям», это снова начинается с начала фактов. Вот почему 'findall/3' существует. :) – lurker