# 9  Set Predicates

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.