# 2  Predicates

More interesting goals are created by applying a special kind of Schelog object called a predicate (or relation) to other Schelog objects. Schelog comes with some primitive predicates, such as the arithmetic operators `%=:=` and `%<`, standing for arithmetic “equal” and “less than” respectively. For example, the following are some goals involving these predicates:

```(%which () (%=:= 1 1)) =>()true
(%which () (%< 1 2))   =>()true
(%which () (%=:= 1 2)) =>#f
(%which () (%< 1 1))   =>#f
```

Other arithmetic predicates are `%>` (“greater than”), `%<=` (“less than or equal”), `%>=` (“greater than or equal”), and `%=/=` (“not equal”).

Schelog predicates are not to be confused with conventional Scheme predicates (such as `<` and `=`). Schelog predicates, when applied to arguments, produce goals that may either succeed or fail. Scheme predicates, when applied to arguments, yield a boolean value. Henceforth, we will use the term “predicate” to mean Schelog predicates. Conventional predicates will be explicitly called “Scheme predicates”.

## 2.1  Predicates Introducing Facts

Users can create their own predicates using the Schelog form `%rel`. For example, let’s define the predicate `%knows`:

```(define %knows
(%rel ()
[('Odysseus 'TeX)]
[('Odysseus 'Scheme)]
[('Odysseus 'Prolog)]
[('Odysseus 'Penelope)]
[('Penelope 'TeX)]
[('Penelope 'Prolog)]
[('Penelope 'Odysseus)]
[('Telemachus 'TeX)]
[('Telemachus 'calculus)]))
```

The expression has the expected meaning. Each clause in the `%rel` establishes a fact: Odysseus knows TeX, Telemachus knows calculus, &c. In general, if we apply the predicate to the arguments in any one of its clauses, we will get a successful goal. Thus, since `%knows` has a clause that reads `[('Odysseus 'TeX)]`, the goal `(%knows 'Odysseus 'TeX)` will be true.

(In the code in this text, brackets have the same behavior as parentheses. We use a mix of brackets and parentheses solely to improve the readability of the code for humans.]

We can now get answers for the following types of queries:

```(%which ()
(%knows 'Odysseus 'TeX))
=>()true

(%which ()
(%knows 'Telemachus 'Scheme))
=>#f
```

## 2.2  Predicates with Rules

Predicates can be more complicated than the above bald recitation of facts. The predicate clauses can be rules, eg,

```(define %computer-literate
(%rel (person)
[(person)
(%knows person 'TeX)
(%knows person 'Scheme)]
[(person)
(%knows person 'TeX)
(%knows person 'Prolog)]))
```

This defines the predicate `%computer‑literate` in terms of the predicate `%knows`. In effect, a person is defined as computer-literate if they know TeX and Scheme, or TeX and Prolog.

Note that this use of `%rel` employs a local logic variable called `person`. In general, a `%rel`-expression can have a list of symbols as its second subform. These name new logic variables that can be used within the body of the `%rel`.

The following query can now be answered:

```(%which ()
(%computer-literate 'Penelope))
=>()true
```

Since Penelope knows TeX and Prolog, she is computer-literate.

## 2.3  Solving Goals

The above queries are yes/no questions. Logic programming allows more: We can formulate a goal with uninstantiated logic variables and then ask the querying process to provide, if possible, values for these variables that cause the goal to succeed. For instance, the query:

```(%which (what)
(%knows 'Odysseus what))
```

asks for an instantiation of the logic variable `what` that satisfies the goal `(%knows 'Odysseus what)`. In other words, we are asking, “What does Odysseus know?”

Note that this use of `%which` — like `%rel` in the definition of `%computer‑literate` — uses a local logic variable, `what`. In general, the second subform of `%which` can be a list of local logic variables. The `%which`-query returns an answer that is a list of bindings, one for each logic variable mentioned in its second subform. Thus,

```(%which (what)
(%knows 'Odysseus what))
=>([what TeX])
```

But that is not all that wily Odysseus knows. Schelog provides a zero-argument procedure (“thunk”) called `%more` that retries the goal in the last `%which`-query for a different solution.

```(%more) =>([what Scheme])
```

We can keep pumping for more solutions:

```(%more) =>([what Prolog])
(%more) =>([what Penelope])
(%more) =>#f
```

The final `#f` shows that there are no more solutions. This is because there are no more clauses in the `%knows` predicate that list Odysseus as knowing anything else.

### 2.3.1  A Note on #f vs ()

It is now clear why `()true` was the right choice for truth in the previous yes/no `%which`-queries that had no logic variables (sec 1). `%which` returns a list of bindings for true goals: the list is empty when there are no variables.

For such Schemes as don’t distinguish between `()` and `#f`, we can still ask fruitful yes/no queries. Simply use a dummy local variable in the `%which`-expression. Truth will give an (ignorable) binding for the dummy variable, while falsity will, as usual, produce `#f`.

```(%which (bingo)
(%knows 'Odysseus 'TeX))
=>([bingo _])

(%which (bingo)
(%knows 'Odysseus 'calculus))
=>#f
```

## 2.4   Asserting Extra Clauses

We can add more clauses to a predicate after it has already been defined with a `%rel`. Schelog provides the `%assert` form for this purpose. Eg,

```(%assert %knows ()
[('Odysseus 'archery)])
```

tacks on a new clause at the end of the existing clauses of the `%knows` predicate. Now, the query:

```(%which (what)
(%knows 'Odysseus what))
```

gives TeX, Scheme, Prolog, and Penelope, as before, but a subsequent `(%more)` yields a new result: `archery`.

The Schelog form `%assert‑a` is similar to `%assert` but adds clauses before any of the current clauses.

Both `%assert` and `%assert‑a` assume that the variable they are adding to already names a predicate (presumably defined using `%rel`). In order to allow defining a predicate entirely through `%assert`s, Schelog provides an empty predicate value `%empty‑rel`. `%empty‑rel` takes any number of arguments and always fails. A typical use of the `%empty‑rel` and `%assert` combination:

```(define %parent %empty-rel)

(%assert %parent ()
[('Laertes 'Odysseus)])

(%assert %parent ()
[('Odysseus 'Telemachus)]
[('Penelope 'Telemachus)])
```

(Schelog does not provide a predicate for retracting assertions, since we can keep track of older versions of predicates using conventional Scheme features (`let` and `set!`).)

## 2.5  Local Variables

The local logic variables of `%rel`- and `%which`-expressions are in reality introduced by the Schelog syntactic form called `%let`. (`%rel` and `%which` are macros written using `%let`.)

`%let` introduces new lexically scoped logic variables. Supposing, instead of

```(%which (what)
(%knows 'Odysseus what))
```

```(%let (what)
This query, too, succeeds five times, since Odysseus knows five things. However, `%which` emits bindings only for the local variables that it introduces. Thus, this query emits `()true` five times before `(%more)` finally returns `#f`.