Topological Sort
Topological Sort

Reputation: 2890

bagof only gives one item, though multiple items fit

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

Answers (3)

false
false

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

Paulo Moura
Paulo Moura

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

CapelliC
CapelliC

Reputation: 60034

Paulo contributed library(yall), autoloaded in SWI-Prolog. Yall (Yet Another Lambda Library) solves your problem easily:

?- bagof(R, {R}/member(r(_,R),[r(_,a), r(_,b), r(_,c), r(_,d)]),Rs).
Rs = [a, b, c, d].

Upvotes: 1

Related Questions