Reputation: 2890
This code works as expected:
?- bagof(R,member(r(R),[r(a),r(b),r(c),r(d)]),Rs).
Rs = [a, b, c, d].
but a similar call, the one I really want, does not:
?- bagof(R,member(r(_,R),[r(_,a), r(_,b), r(_,c), r(_,d)]),Rs).
Rs = [a]
;
gives me more answers -- but I want [a,b,c,d]
. What's my fix?
Upvotes: 4
Views: 569
Reputation: 10142
bagof/3
and _
do not flock together directly. Same is true for setof/3
.
So either give all those anonymous variables a name and declare them as a local variable, use an auxiliary predicate, or use library(lambda)
:
?- bagof(R,R+\member(r(_,R),[r(_,a), r(_,b), r(_,c), r(_,d)]),Rs).
Rs = [a,b,c,d].
Upvotes: 3
Reputation: 18683
You need to existentially qualify the arguments that you're not interested in instead of using anonymous variables:
?- bagof(R,A^A1^A2^A3^A4^member(r(A,R),[r(A1,a), r(A2,b), r(A3,c), r(A4,d)]),Rs).
Rs = [a, b, c, d].
This is necessary as bagof/3
(and setof/3
) will return a bag (set) of solutions for each instantiation of the free variables (i.e. the variables in the goal that are not in the template). In alternative, you can use the findall/3
predicate (which ignores free variables):
?- findall(R,member(r(A,R),[r(A1,a), r(A2,b), r(A3,c), r(A4,d)]),Rs).
Rs = [a, b, c, d].
But note that findall/3
returns an empty list when there are no solutions while bagof/3
(and setof/3
) fail when there are no solutions.
Another alternative to avoid a long list of existentially qualified variables in calls to bagof/3
and setof/3
is to introduce an auxiliary predicate with a single clause whose head only lists the arguments you're interested in. For example:
r(R) :-
member(r(_,R),[r(_,a), r(_,b), r(_,c), r(_,d)]).
?- bagof(R, r(R), Rs).
Rs = [a, b, c, d].
Upvotes: 2