лучая все решения с помощью перебора, при получении нового реш-я предыдущее становится недоступным. Предикаты порождения позволяют получить доступ ко всем решениями сразу, собирая их в список.
Предикат bagof(x,p,l) порождает список L всех объектов X, удовлетвор-х цели P. X и P должны содержать общие переменные. Если нет ни одного решения, то согласование цели завершается неудачей. Если один и тот же Х найден многократно, то все его экземпляры будут в списке.
класс(а,глас). класс(b,согл). класс(с, согл). класс(в,согл). класс(e,глас). класс(b,согл).
?-bagof(x,класс(х,согл),L). L=[b,c,d,f].
Если цель будет содержать другие не конкретизированные переменные, то для каждой из возможных конкретизаций этих переменных получается свой список решений: ?-bagof(x,класс(х,класс), L). класс=глас, L=[a,e]; класс=согл, L=[b,c,d,f]; no
Предикат setoff(X,P.L) работает аналогично bagof, но список L упорядоч.
и не содержит повторяющихся элементов. ?-setof(класс/x,класс(х,класс),L). L=[глас/a,глас/e,согл/b,согл/c,согл/d,согл/f]
Предикат findall(X,P,L) отличается от предиката bagof тем, что собирает в список L все объекты Х, удовлетворяющие цели P, не обращая внимания на конкретизации тех переменных, которых нет в Х. Если не существует ни одного решения, то цель findall(X,P,L) все равно успешна и L=[].
Дополнение: предикаты порождения модно определить, используя предикаты assert и retract: findall(X.P.L):-P,assert(нашли(Х)), fail; собрать(L). собрать([X