### 11.2.3 `setof/3`

The `setof/3` predicate is basically the same as `bagof`, but with one useful difference: the lists it contains are ordered and contain no redundancies (that is, each item appears in the list only once).

For example, suppose we have the following database

`age(harry,13).age(draco,14).age(ron,13).age(hermione,13).age(dumbledore,60).age(hagrid,30).`

Now suppose we want a list of everyone whose age is recorded in the database. We can do this with the query:

`findall(X,age(X,Y),Out). X = _8443  Y = _8448  Out = [harry,draco,ron,hermione,dumbledore,hagrid]`

But maybe we would like the list to be ordered. We can achieve this with the following query:

`setof(X,Y ^ age(X,Y),Out).`

(Note that, just like with`bagof`, we have to tell `setof` not to generate separate lists for each value of `Y`, and again we do this with the `^` symbol.)

This query yields:

`X = _8711  Y = _8715  Out = [draco,dumbledore,hagrid,harry,hermione,ron]`

Note that the list is alphabetically ordered.

Now suppose we are interested in collecting together all the ages which are recorded in the database. Of course, we can do this with the following query:

`findall(Y,age(X,Y),Out). Y = _8847  X = _8851  Out = [13,14,13,13,60,30] `

But this output is rather messy. It is unordered and contains repetitions. By using `setof` we get the same information in a nicer form:

`setof(Y,X ^ age(X,Y),Out). Y = _8981  X = _8985  Out = [13,14,30,60] `

Between them, these three predicates offer us a lot of flexibility. For many purposes, all we need is `findall`. But if we need more, `bagof` and `setof` are there waiting to help us out.

Patrick Blackburn, Johan Bos and Kristina Striegnitz
Version 1.2.5 (20030212)