A  fundamental  unit  of  a  logic  program  is the goal or procedure call.
Examples are:-

              gives(tom,apple,teacher)   reverse([1,2,3],L)   X<Y

A  goal is merely a special kind of term, distinguished only by the context
in  which  it appears in the program.  The (principal) functor of a goal is
called  a predicate.  It corresponds roughly to a verb in natural language,
or to a procedure name in a conventional programming language.

A  logic  program  consists  simply  of  a  sequence  of  statements called
sentences,  which  are  analogous  to  sentences  of  natural  language.  A
sentence comprises a head and a body.  The head either consists of a single
goal  or  is  empty.  The body consists of a sequence of zero or more goals
(ie.   it  too  may  be  empty).  If the head is not empty, the sentence is
called a clause.

If  the  body  of  a  clause  is non-empty, the clause is called a non-unit
clause, and is written in the form:-

                                 P :- Q, R, S.

where  P  is  the  head goal and Q, R and S are the goals which make up the
body.  We can read such a clause either declaratively as:-

                     "P is true if Q and R and S are true."

or procedurally as:-

                 "To satisfy goal P, satisfy goals Q, R and S."


If  the  body of a clause is empty, the clause is called a unit clause, and
is written in the form:-

                                       P.

where P is the head goal.  We interpret this declaratively as:-

                                  "P is true."

and procedurally as:-
                             "Goal P is satisfied."


A  sentence  with  an  empty  head is called a directive, of which the most
important kind is called a question and is written in the form:-

                                     P, Q ?

where  P  and  Q  are  the  goals  of  the  body.   Such a question is read
declaratively as:-

                              "Are P and Q true?"

and procedurally as:-

                            "Satisfy goals P and Q."


Sentences  generally  contain  variables.  Note that variables in different
sentences are completely independent, even if they have the same name - ie.
the  "lexical  scope"  of a variable is limited to a single sentence.  Each
distinct  variable  in  a sentence should be interpreted as standing for an
arbitrary  entity, or value.  To illustrate this, here are some examples of
sentences  containing  variables,  with possible declarative and procedural
readings:-

     (1)     employed(X) :- employs(Y,X).

     "Any X is employed if any Y employs X."

     "To find whether a person X is employed,
     find whether any Y employs X."

     (2)     derivative(X,X,1).

     "For any X, the derivative of X with respect to X is 1."

     "The goal of finding a derivative for the expression X
     with respect to X itself is satisfied by the result 1."

     (3)     ungulate(X), aquatic(X) ?

     "Is it true, for any X, that X is an ungulate and X is
     aquatic?"

     "Find an X which is both an ungulate and aquatic."

In any program, the procedure for a particular predicate is the sequence of
clauses  in  the  program whose head goals have that predicate as principal
functor.  For example, the procedure for a ternary predicate 'append' might
well consist of the two clauses:-

     append([X,..L1],L2,[X,..L3]) :- append(L1,L2,L3).
     append([],L,L).


where  'append(L1,L2,L3)'  means  "the list L1 appended with the list L2 is
the list L3".

Certain  predicates  are  predefined by built-in procedures supplied by the
Prolog system.  Such predicates are called evaluable predicates.

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

     grandfather(X,Z) :-
          (mother(X,Y) | father(X,Y)), father(Y,Z).

which can be read as:-

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

Such  uses  of  disjunction  can  always be eliminated by defining an extra
predicate - for instance the previous example is equivalent to:-

     grandfather(X,Z) :- parent(X,Y), father(Y,Z).
     parent(X,Y) :- mother(X,Y).
     parent(X,Y) :- father(X,Y).
