Sumar
findall/3, bagof/3 și setof/3 rezolvă aceeași problemă: adună într-o listă toate soluțiile unei interogări. Diferența e în ce fac când nu există nicio soluție și dacă filtrează duplicatele.
Sintaxă
findall(Template, Goal, List).
bagof(Template, Goal, List).
setof(Template, Goal, List).
Template— forma fiecărui element care va ajunge înList(tipic, o variabilă dinGoal)Goal— proprietatea care trebuie satisfăcutăList— rezultatul
Comportament
| Predicat | Lista vidă când nu există soluții? | Elimină duplicatele? |
|---|---|---|
| findall/3 | Da, returnează [] | Nu |
| bagof/3 | Nu, eșuează (false) | Nu |
| setof/3 | Nu, eșuează (false) | Da, sortează crescător |
Exemple
Toate perechile (X, Y) din [2..6] cu Y divizor al lui X (din breviar):
divisorsPairs(A, B, List) :-
numlist(A, B, Range),
findall((X, Y), (member(X, Range), member(Y, Range), X mod Y =:= 0), List).
?- divisorsPairs(2, 6, LR).
LR = [(2,2), (3,3), (4,2), (4,4), (5,5), (6,2), (6,3), (6,6)]
bagof cu un predicat din baza de cunoștințe (Lab 2):
?- bagof(X, parent_of(X, sam), List).
List = [sandra, ben]
Idiomuri
Filtrare cu condiție — modelul cel mai des întâlnit în parțial:
% toți angajații cu salariul >= MinSalary
employee_with_good_salary(InputList, MinSalary, Result) :-
findall(Name,
(member(employee_salary(Name, Salary), InputList), Salary >= MinSalary),
Result).
Generate-and-test peste un interval:
numlist(A, B, Range),
findall(X, (member(X, Range), proprietate(X)), Result).
Eliminarea duplicatelor folosind setof sau, alternativ, post-procesare cu sort/2 (care elimină duplicatele):
findall(X, predicat(X), L), sort(L, LDistinct).