As we have seen, the goals in the body of a sentence are linked
by the operator ,, which can be interpreted as conjunction (and).
It is sometimes convenient to use an additional operator |, standing
for disjunction (or). (The precedence of | is such that it
dominates , but is dominated by :-.) An example is the clause (A), which can be read as (B).
grandfather(X, Z) :-
( mother(X, Y)
| father(X, Y)
),
father(Y, Z). (A)
``For any X, Y, and Z,
X has Z as a grandfather if
either the mother of X is Y
or the father of X is Y,
and the father of Y is Z.'' (B)
Such uses of disjunction can usually be eliminated by defining an extra predicate. For instance, (A) is equivalent to (C)
grandfather(X, Z) :- parent(X, Y), father(Y, Z).
parent(X, Y) :- mother(X, Y).
parent(X, Y) :- father(X, Y). (C)
Therefore, disjunction will not be mentioned further in the following more formal description of the semantics of clauses.
For historical reasons, the token |, when used outside a list, is
actually an alias for ;. The aliasing is performed when terms
are read in, so that (D) is read as if it were (E) thus you can use
; instead of | for disjunction if you like.
a :- b | c. (D)
a :- b ; c. (E)
Note the double use of the . character. Here it is used as
a sentence terminator, while in other instances it may be used in a string of
symbols that make up an atom (for example, the list functor .). The
rule used to disambiguate terms is that a . followed by a
layout-character is regarded as the sentence
terminator full-stop, where a
layout-character is defined to be any character less than or equal to ASCII 32
(this includes space, tab, newline, and all control characters).