As SWI-Prolog Manual said, forall/2 is well suited to be used for side effects, but it doesn’t work with backtrackable effects. Details see https://swi-prolog.discourse.group/t/careful-with-forall-2-when-it-is-used-for-side-effects
However, what if I want forall/2 behavior but keep backtrackable side-effect?
For example,
:- use_module(library(chr)).
:- chr_constraint c/2, r/2.
c(X,Y) <=> Y=X, r(X,Y).
If using forall/2:
?- forall(between(1,3,X), c(X,_)).
true.
If using foreach/2:
?- foreach(between(1,3,X), c(X,_)).
false.
I know why the above two queries return true
and false
, but what I really require is
?- for_?_(between(1,3,X), c(X,_)).
r(3,3),
r(2,2),
r(1,1).
My current workaround is using findall/3 + maplist/2:
foreach2(Generator, Goal) :-
findall(Goal, Generator, Goals),
maplist(call, Goals).
?- foreach2(between(1,3,X), c(X,_))
r(3,3),
r(2,2),
r(1,1).
The question is that
Is there any built-in predicate do the same thing?
Thanks.