/* bagof1(O,P,L) construit la liste L des objets O verifiant la 
   propriete P. O est un terme qui contient des variables liees
   a celles de P */

mybagof(O,P,L):-
	P,
	add_mylist(O),
	fail.

mybagof(_,_,L) :- !,
	retract(mylist(L-[])).

add_mylist(O) :-
	not(mylist(_)), ! ,
	L = [O|S],
	assert(mylist(L-S)).

add_mylist(O) :- 
	retract(mylist(L-S)),
	S=[O|S1], 
	assert(mylist(L-S1)).
	

mysetof(O,P,L) :-
	mybagof(O,P,L1),
	sort(L1,L).

/* tests */

p(b).
p(a).
p(c).
p(a).
p(d).

a([b,[c,d1],e]).
a([b1,[c,d2],e]).
a([b2,[c,d2],e]).
a([b,[c,d4],e]).

t1(L):-
	mybagof(O,p(O),L).
t2(L):-
	mybagof(O,a([_,[_,O],_]),L).

t3(L):-
	mysetof(O,p(O),L).
t4(L):-
	mysetof(O,a([_,[_,O],_]),L).

/*

File set_and_bag consulted

true
| ?- mybagof(O,p(O),L).

O = _453
L = [b,a,c,a,d]

true
| ?- mybagof(O,a([_,[_,O],_]),L).

O = _453
L = [d1,d2,d2,d4]

true
| ?- mysetof(O,p(O),L).

O = _453
L = [a,b,c,d]

true
*/







