Я рекомендую вам посетить эту страницу , особенно если вы используете swi-prolog.
Существует 4 предиката, которые делают то, что вы хотите: findall/3
, findall/4
, bagof/3
и setof/3
.
Подводя итог, вот предикат теста, с которым я буду работать:
test(0, 3).
test(1, 3).
test(2, 5).
test(3, 4).
Сначала самое простое - findall / 3 и findall / 4:
?- findall(C, test(X, C), Cs).
Cs = [3, 3, 5, 4].
?- findall(C, test(X, C), Cs, TailCs).
Cs = [3, 3, 5, 4|TailCs].
Они просто возвращают все альтернативы, с дубликатами, без сортировки, без привязки других свободных переменных, как обычный список для findall/3
и список различий для findall/4
.оба предиката findall
s успешно завершаются, когда список пуст.
Затем bagof.По сути, bagof/3
работает как findall/3
, но связывает свободные переменные.Это означает, что тот же запрос, что и выше, но с bagof/3
возвращает:
?- bagof(C, test(X, C), Cs).
X = 0,
Cs = [3] ;
X = 1,
Cs = [3] ;
X = 2,
Cs = [5] ;
X = 3,
Cs = [4].
Говоря bagof/3
не связывать все свободные переменные, вы получаете findall/3
:
?- bagof(C, X^test(X, C), Cs).
Cs = [3, 3, 5, 4].
Тем не менее, вы должны заметить, что bagof/3
терпит неудачу, когда результат пустой, где findall/3
нет.
Наконец, setof/3
.Это в основном bagof/3
, но с отсортированными результатами и без дубликатов:
?- setof(C, X^test(X, C), Cs).
Cs = [3, 4, 5].