why findall/3 in swi-prolog ignores variable binding?

816 views Asked by At

The following codes give these results:

?- X = a, findall(Element, ( member(Z, [a,b,c]), Element = Z:X  ), Set).
X = a,
Set = [a:a, b:a, c:a].

But when I want that all elements will share the same unbound variable (instead of a), then things are not working as it is supposed:

?- X = Y, findall(Element, ( member(Z, [a,b,c]), Element = Z:X  ), Set).
X = Y,
Set = [a:_G1918, b:_G1912, c:_G1906]. 

Why _G1918, _G1912, and _G1906 are not bound to each other? is that a bug in swi-prolog?

2

There are 2 answers

1
Tudor Berariu On BEST ANSWER

You can use bagof/3 for that:

?- X = Y, bagof(Element, Z^( member(Z, [a,b,c]), Element = Z:X  ), Set).
X = Y,
Set = [a:Y, b:Y, c:Y].

From SWI-Prolog's documentation:

findall/3 is equivalent to bagof/3 with all free variables bound with the existential operator (^), except that bagof/3 fails when Goal has no solutions.

In your query X is a free variable, so the result you get is the same with the one for bagof/3 with X^:

?- X = Y, bagof(Element, X^Z^( member(Z, [a,b,c]), Element = Z:X  ), Set).
X = Y,
Set = [a:_G2115, b:_G2109, c:_G2103].
3
CapelliC On

it's not a bug, the 'all solutions' builtins differs in variable quantification handling.

findall/3 it's the simpler model. For your case, bagof/3 will work, but you'll need to indicate the aggregation variable:

?- X = Y, bagof(Element, Z^( member(Z, [a,b,c]), Element = Z:X  ), Set).
X = Y,
Set = [a:Y, b:Y, c:Y].