Search code examples
prologprolog-setofprolog-findall

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


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?


Solution

  • 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].