The goal
(%bag-of X G Bag)
unifies with Bag the list of all instantiations of
X for which G succeeds. Thus, the following query
asks for all the things known -- ie, the collection of things
such that someone knows them:
(%which (things-known) (%let (someone x) (%bag-of x (%knows someone x) things-known))) => ([things-known (TeX Scheme Prolog Penelope TeX Prolog Odysseus TeX calculus)])
This is the only solution for this goal:
(%more) => #f
Note that some things -- eg, TeX -- are enumerated
more than once. This is because more than one person knows
TeX. To remove duplicates, use the predicate
%set-of
instead of %bag-of:
(%which (things-known) (%let (someone x) (%set-of x (%knows someone x) things-known))) => ([things-known (TeX Scheme Prolog Penelope Odysseus calculus)])
In the above, the free variable someone in the
%knows-goal is used as if it
were existentially quantified. In contrast, Prolog's
versions of
%bag-of and %set-of fix it for each solution of the
set-predicate goal. We can do it too with some additional
syntax that identifies the free variable.
Eg,
(%which (someone things-known) (%let (x) (%bag-of x (%free-vars (someone) (%knows someone x)) things-known))) => ([someone Odysseus] [things-known (TeX Scheme Prolog Penelope)])
The bag of things known by one someone is returned. That someone is Odysseus. The query can be retried for more solutions, each listing the things known by a different someone:
(%more) => ([someone Penelope] [things-known (TeX Prolog Odysseus)]) (%more) => ([someone Telemachus] [things-known (TeX calculus)]) (%more) => #f
Schelog also provides two variants of these set predicates,
viz., %bag-of-1 and %set-of-1. These act like %bag-of
and %set-of but fail if the resulting bag or set is empty.