Conceptefindall / bagof / setof (generate-and-test)

findall / bagof / setof (generate-and-test)

Colectează toate soluțiile unei interogări într-o listă. Cel mai important pattern din parțial.

11 exerciții folosesc acest concept recursivitate-pe-listepredicate-predefinite-pe-liste

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 în List (tipic, o variabilă din Goal)
  • 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).

Exerciții care folosesc acest concept