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”.

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

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.

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.

It is now clear why `()`

was the right choice for truth in
the previous yes/no ^{true}`%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

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!`

).)

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))

we had asked

(%let (what) (%which () (%knows 'Odysseus 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 `()`

five times before
^{true}`(%more)`

finally returns `#f`

.