В SWI Пролог foreach / 2 мы читаем:
Совместимость «агрегатной» библиотеки, которая содержит предикат foreach/2
заявлен как
Quintus, SICStus 4. forall / 2 является встроенным SWI-Prolog, а term_variables / 3 является SWI-Prolog встроенный с различной семантикой.
Из документации SICStus Prolog :
foreach(:Generator, :Goal)
для каждого доказательства Генератор в свою очередь, мы делаем копию Goal с соответствующей заменой, затем выполняем эти копии последовательно. Например, foreach(between(1,3,I), p(I))
эквивалентно p(1), p(2), p(3)
.
Обратите внимание, что это не то же самое, что forall/2
. Например, forall(between(1,3,I), p(I))
эквивалентно
\+ \+ p(1), \+ \+ p(2), \+ \+ p(3)
.
Хитрость в foreach/2
состоит в том, чтобы гарантировать, что переменные Goal , которые не встречаются в Генератор восстановлен правильно. (Если таких переменных нет, вы также можете использовать forall/2
.)
Как и forall/2
, этот предикат выполняет l oop, управляемый сбоем, по сравнению с Generator . В отличие от forall/2
, Цели выполняются как обычное соединение и могут быть успешными несколькими способами.
Взяв пример на странице Пролог SWI, без окончательной объединение:
?- foreach(between(1,4,X), dif(X,Y)).
dif(Y, 4),
dif(Y, 3),
dif(Y, 2),
dif(Y, 1),
dif(Y, 1),
dif(Y, 2),
dif(Y, 1),
dif(Y, 1),
dif(Y, 3),
dif(Y, 2),
dif(Y, 1),
dif(Y, 1),
dif(Y, 2),
dif(Y, 1),
dif(Y, 1).
Я не уверен, почему есть выходные данные всех dif/2
экземпляров и почему есть повторения одной и той же подцели.
foreach/2
должно быть решено что соединение нескольких dif(Y,i)
истинно, поскольку несвязанная переменная Y
явно dif
из целого числа i .
Но теперь:
?- foreach(between(1,4,X), dif(X,Y)), Y = 5.
Y = 5.
Хорошо, поэтому ничего не выводится, кроме Y=5
, потому что цель успешна. Но что меняет Y=5
? После foreach/2
Пролог уже может решить, что foreach/2
истинно (учитывая состояние Y
во время запуска foreach/2
), поэтому добавление Y=5
ничего не должно изменить.
Но тогда:
?- foreach(between(1,4,X), dif(X,Y)), Y = 2.
false.
Последующее объединение меняет исход foreach/2
. Как?
Я подумал, что freeze/2
на Y
может помочь сделать ситуацию интересной, потому что в действительности мы вычисляем:
freeze(Y,foreach(between(1,4,X), dif(X,Y))).
Это более или менее объясняет распечатки. Например:
?- freeze(Y,foreach(between(1,4,X), dif(X,Y))).
freeze(Y, foreach(between(1, 4, X), dif(X, Y))).
?- freeze(Y,foreach(between(1,4,X), dif(X,Y))), Y=5.
Y = 5.
?- freeze(Y,foreach(between(1,4,X), dif(X,Y))), Y=2.
false.
Это то, что происходит?