[net.lang.prolog] PROLOG Digest V4 #18

PROLOG-REQUEST@SU-SCORE.ARPA (Chuck Restivo, The Moderator) (06/10/86)

PROLOG Digest            Tuesday, 10 Jun 1986      Volume 4 : Issue 18

Today's Topics:
                          Review - Turbo-P,
                Implementations - Assert & KBES Tools,
                         LP Library - Update
----------------------------------------------------------------------

Date: Thu Jun  5 21:45:42 1986
From: Herm Fischer <hermix!fischer@rand-unix.ARPA>
Reply-to: HFischer@ada20
Subject: Borland Turbo Prolog

I received a copy of Borland Turbo Prolog, and have
a few initial impressions to convey.  (I presently
have been mostly using UNSW prolog under Xenix on
the PC/AT.)

It is a true compiler, and code executes quite fast.
Some examples of LIPS (logical inferences per second)
of test programs (from the net):

TEST                             PC-AT*       PC-CONVERTABLE
FUNCTION                       UNSW**   TURBO        TURBO

naive reverse (30 items list)      550     9920         4509
quicksort (reverse order list)     385     8760***      2390
quicksort (ordered list)           495     8736         3559

     ---------------
*  - PC/AT has 14.6 MHz crystal installed
     PC Convertable (new laptop) is unmodified
** - UNSW interpreter timings under Xenix 3.0 version, huge
     mem. model Turbo-Prolog timings under MSDOS 3.2
*** - seems inconsistant, but that's the empirical number

>From the speed, and the presence of a full set of features,
I'd say this is one of the first Prolog compilers which is
truly usable for real applications.  (It is a bit amazing to
me to have 4500 lips running in a laptop battery powered
computer!)

Features include a very nice user interface (multi-window
system); debugging is done with a trace in one window, the
printed dialog output in another, and the source code in a
third window... the source code steps thru as the trace
progresses, allowing reediting and recompiling from the
middle of a trace without loosing the contents of the
screen  windows.  The window system is also usable by
applications.

The language is typed, leading to some conversion
difficulties for old Prolog programs with sloppy naming
habits.  Ada programmers will love it; Prolog hackers
may have to learn new habits.  Typing allows defining
types, weak subtypes, and enforced rules of parameter
checks.  This should be a real benefit to developers of
code which must be maintained by crews of programmers
other than the original authors... (though a bit of a
pain for quick and dirty work or conversion of old code)

The syntax is true Clocksin & Mellish.

Some features missing in the first release include arg
and functor (said to be comming out "real soon maybe"),
parentheses nesting of subgoals (hardly ever used
anyway), and findall/bagof restricted to simple atoms
and lists of elements.

I expect this product to legitimize Prolog for the semi
mass market!

-- Herm Fischer

------------------------------

Date: Sun, 8 Jun 86 11:15:18 EST
From: munnari!basser.oz!anand@seismo.CSS.GOV
Subject: 'assert' considered harmful

People tend to use 'assert' as caching mechanism
for inferences  because of the absence of a built-in
predicate, say, 'assume', which can perform the task
which David Sherman wants. 'assume' can be seen as a
default rule. As long as you have no information that
will invalidate rule X, you can assume(X). In this
case it is equivalent to saying that as long as the
year is 1986, assume(control(Taxpayer1,Taxpayer2)).
If the year is 1987 and Taxpayer1 no longer controls
Taxpayer2 then some of the inferences drawn earlier
may no longer be valid in the new context. The necessary
changes which have to be done to the knowledge-base is
precisely what TMS or  ATMS(Assumption based Truth
Maintenance System) does. Of course, assert cannot be
used instead of assume, because what is asserted is a
THEOREM(true at all times) and not an assumption.
By the way, is anyone over the net aware of a Prolog
implementation with a built-in TMS or ATMS like mechanism,
which provides facilities for 'assuming' and 'retracting'
assumptions.

PS: Let us remember that GOTO was given up(more or less)
because of the availability of better control structures
like FOR & WHILE loops. So if we want 'assert' not to be
misused, let us assert that we need 'assume' and not
assume that 'assert' will do the job for us.

-- Anand S.Rao

------------------------------

Date: 4 Jun 86 18:20:54 GMT
From: hplabs!hao!seismo!mcvax!ukc!icdoc!cdsm@ucbvax.berkeley
Subject: Monkeys & bananas

>From: VERACSD@USC-ISI.ARPA
>Subject: Benchmarking KBES-Toools
>
>I have come across some recent benchmarks from NASA (U.S.
>Gov't MEMORANDUM from the FM7/AI Section, April 3, 1986)
>which compared various KBES tools' (ART, OP, KEE & CLIPS)
>times for solving the MONKEY-AND-BANANA problem.  (This
>toy problem is explained in detail along with OPS source
>in Brownston et. al.'s "Programming Expert Systems in OPS5".)
>
>Although the benchmarks include backward-chaining solutions
>to the problem in both KEE and ART (along with forward
>chaining counterparts), there is no PROLOG implementation
>in the comparison.  I am very interested in a  PROLOG
>comparison, and am in the process of implementing one.

Here is  a Prolog solution. It uses much the same logic
as the Brownston book (i.e. forward chaining), though
I've only used "working memory" (the State variables)
for states not goals - this makes it much easier to
incorporate subgoals, which is the reason there are
basically 6 rules (equivalent to 14 Horn Clauses)
rather than 26 in the OPS5 version (though there are
also 21 subsidiary clauses). I've also removed the
"state independent assertions" (light & heavy) from
state, though they could be there. The Prolog solution
takes 92 lines compared with 201 (non-comment) lines
for OPS5. This includes the code for "modify" etc.
which is not included in the OPS5 total. There are
various packages on the market which are implemented
in Prolog but provide the same kind of facilities.

>(By the way, the time to beat is 1.2 secs. for a
>forward-chaining implementation using ART on a
>3640 with 4MB main-memory.)

That's pretty easy. The code below runs in about
0.32 secs on a VAX 750 using the CProlog
interpreter. With a compiler on the DEC 20
you should be able to do an order of magnitude
faster (most of the time is probably spent in i/o
anyway).

I've included the timing routines at the end. You
may have to alter the "cputime" routine to fit your
local Prolog system.

-- Chris Moss
   Imperial College

/*
monkey & bananas problem from Brownston & al:
Programming Expert Systems in OPS5 (Addison
Wesley 1985)
*/

test(X) :-
    problem(X, Goal, State),
    (goal(Goal,State,NewS) ->
writeline(['Congratulations, the goals are satisfied'])
; writeline(['Impossible, the goal',Goal,'cannot be achieved']),fail).

problem(general, hold(bananas),
    [monkey([7,7],couch,blanket),
     obj(bananas,[9,9],ceiling),
     obj(couch,[7,7],floor),
     obj(ladder,[4,3],floor),
     obj(blanket,[7,7],_)]).

light(bananas).
light(ladder).
light(blanket).
heavy(couch).

/* goal(X,State,New) :-
    writeline([goal,X,in,State]), fail.
*/
goal(hold(Object), State,NewS) :-
    hold(Object, State) ->
           NewS=State
    ;  light(Object) ->
       approach(Object, State, State2),
       goal(hold(nil), State2,State3),
       modify(hold(Object),State3,State4),
       modify(on(Object,monkey),State4,NewS),
       writeline([monkey,grabs,Object])
    ; Object=nil,
       hold(Obj,State),
       modify(hold(nil),State,State2),
       modify(on(Obj,floor),State2,NewS),
      writeline([monkey,drops,Obj]).

goal(at(Loc), State, NewS) :-
    at(Loc,State) ->
      NewS=State
    ; goal(on(floor), State, State2),
      goal(hold(nil), State2, State3),
      modify(at(Loc),State3,NewS),
      writeline([monkey,walks,to,Loc]).

goal(at(Object,Loc), State,NewS) :-
    at(Object,Loc,State) ->
      NewS=State
    ; goal(hold(Object),State,State2),
      goal(on(floor),State2,State3),
      modify(at(Loc),State3,State4),
      modify(at(Object,Loc),State4,NewS),
      writeline([monkey,carries,Object,to,Loc]).

goal(on(Object), State, NewS) :-
    ison(Object, State) ->
      NewS=State
    ; Object=floor ->
      modify(on(floor),State,NewS),
      writeline([monkey,jumps,to,floor])
    ; object(Object),
      goal(hold(nil),State,State2),
      at(Object, Loc, State2),
      goal(at(Loc),State2,State3),
      modify(on(Obj),State3,NewS),
      writeline([monkey,climbs,on,Object]).
/* goal(X,State,New) :-
      writeline(['** fail goal',X,in,State]),
      fail.
*/

approach(Object, State, NewS) :-
    ison(Object,ceiling,State) ->
      at(Object,Loc,State),
      goal(at(ladder,Loc),State,State2),
      goal(on(ladder), State2, NewS)
    ; at(Object,Loc,State),

/*  window : support routines */
      goal(at(Loc),State,NewS).
at(Loc,State) :-
    inn(monkey(Loc,_,_),State).
at(Object,Loc,State) :-
    inn(obj(Object,Loc,_),State).

hold(Object,State) :-
    inn(monkey(_,_,Object),State).

ison(On,State) :-
     inn(monkey(_,On,_),State).
ison(Object,On,State)  :-
     inn(obj(Object,_,On),State).

modify(at(Loc),State,NewS) :-
    change(monkey(_,On,Holds),monkey(Loc,On,Holds),State,NewS).
                                        
modify(at(Object,Loc), State,NewS) :-
     change(obj(Object,_,On),obj(Object,Loc,On),State,NewS).
                                        
modify(hold(Object),State,NewS) :-
    change(monkey(At,On,_), monkey(At,On,Object),State, NewS).
                                        
modify(on(Object), State,NewS) :-
     change(monkey(At,_,Holds), monkey(At,Object,Holds),State, NewS).
                                        
modify(on(Object,On), State, NewS) :-
     change(obj(Object,At,_), obj(Object,At,On),State, NewS).
                                        
object(X) :- heavy(X) ; light(X).

inn(X, [X|_]).
inn(X, [_|Y]) :- inn(X,Y).

change(Old,New,[Old|List], [New|List]).
change(Old,New, [Other|List], [Other|Newlist]) :-
    change(Old,New, List, Newlist).

writeline([]) :- nl.
writeline([A|B]) :-
    write(A), write(' '),
    writeline(B).

/* timing code */
testit(X) :- cputime(S1), test,
      cputime(S2), test2,
      cputime(S3),
      X is (S2-S1-S3+S2)/10.

/* this works for Cprolog but maybe not for others */
cputime(X) :- X is cputime.

for(X,X,Y).
for(X,Y,Z) :- Y < Z, Y1 is Y+1, for(X,Y1,Z).

test :- for(X,1,10), test1, fail.
test.
test1 :- test(general), !.

test2 :- for(X,1,10), dummy, fail.
test2.
dummy.

------------------------------

Date: 5 Jun 86 08:12:00 EST
From: "CUGINI, JOHN" <cugini@nbs-vms.ARPA>
Subject: C-Prolog manual enhancements

For what it's worth, here are some things we've developed to
enhance/correct the C-Prolog manual for version 1.5.  I haven't
seen anything like this around, so here's hoping this will
save everyone from doing the same work.  There are four chunks:

1. a table of contents

2. an errata sheet

3. an improved summary of evaluable predicates, including several
   ones missing from the original, and page references

4. a syntax summary

Feel free to copy/improve, etc.

John Cugini  <Cugini@nbs-vms>
Institute for Computer Sciences and Technology
National Bureau of Standards



                                 Table of Contents
       
                        C-Prolog User's Manual, Version 1.5
       
       1   Using C-Prolog  . . . . . . . . . . . . . . . . . . . . . .  1
       1.1   Preface . . . . . . . . . . . . . . . . . . . . . . . . .  1
       1.2   Using C-Prolog -- Overview  . . . . . . . . . . . . . . .  1
       1.3   Access to C-Prolog  . . . . . . . . . . . . . . . . . . .  2
       1.4   Reading-in Programs . . . . . . . . . . . . . . . . . . .  2
       1.5   Directives:  Questions and Commands . . . . . . . . . . .  3
       1.6   Saving A Program  . . . . . . . . . . . . . . . . . . . .  5
       1.7   Restoring A Saved Program . . . . . . . . . . . . . . . .  5
       1.8   Program Execution And Interruption  . . . . . . . . . . .  5
       1.9   Nested Executions -- Break and Abort  . . . . . . . . . .  5
       1.10  Exiting From The Interpreter  . . . . . . . . . . . . . .  6
       
       2   Prolog Syntax . . . . . . . . . . . . . . . . . . . . . . .  6
       2.1   Terms . . . . . . . . . . . . . . . . . . . . . . . . . .  6
       2.2   Operators . . . . . . . . . . . . . . . . . . . . . . . .  8
       2.3   Syntax Errors . . . . . . . . . . . . . . . . . . . . . . 10
       2.4   Using a Terminal without Lower-Case . . . . . . . . . . . 10
       
       3   The Meaning of Prolog Programs  . . . . . . . . . . . . . . 11
       3.1   Programs  . . . . . . . . . . . . . . . . . . . . . . . . 11
       3.2   Declarative and Procedural Semantics  . . . . . . . . . . 13
       3.3   Occurs Check  . . . . . . . . . . . . . . . . . . . . . . 14
       3.4   The Cut Symbol  . . . . . . . . . . . . . . . . . . . . . 14
       
       4   Debugging Facilities  . . . . . . . . . . . . . . . . . . . 15
       4.1   The Procedure Box Control Flow Model  . . . . . . . . . . 15
       4.2   Basic Debugging Predicates  . . . . . . . . . . . . . . . 17
       4.3   Tracing . . . . . . . . . . . . . . . . . . . . . . . . . 17
       4.4   Spy Points  . . . . . . . . . . . . . . . . . . . . . . . 17
       4.5   Format of Debugging Messages  . . . . . . . . . . . . . . 18
       4.6   Options Available during Debugging  . . . . . . . . . . . 19
       4.7   Reconsulting during Debugging . . . . . . . . . . . . . . 20
       
       5   Evaluable Predicates  . . . . . . . . . . . . . . . . . . . 21
       5.1   Input and Output  . . . . . . . . . . . . . . . . . . . . 21
       5.1.1   Reading-in Programs . . . . . . . . . . . . . . . . . . 22
       5.1.2   File Handling . . . . . . . . . . . . . . . . . . . . . 22
       5.1.3   Input and Output of Terms . . . . . . . . . . . . . . . 23
       5.1.4   Character Input/Output  . . . . . . . . . . . . . . . . 23
       5.2   Arithmetic  . . . . . . . . . . . . . . . . . . . . . . . 24
       5.3   Convenience . . . . . . . . . . . . . . . . . . . . . . . 26
       5.4   Extra Control . . . . . . . . . . . . . . . . . . . . . . 26
       5.5   Meta-Logical  . . . . . . . . . . . . . . . . . . . . . . 27
       5.6   Sets  . . . . . . . . . . . . . . . . . . . . . . . . . . 28
       5.7   Comparison of Terms . . . . . . . . . . . . . . . . . . . 29
       5.8   Modification of the Program . . . . . . . . . . . . . . . 31
       5.9   Information about the State of the Program  . . . . . . . 32
       5.10  Internal Database . . . . . . . . . . . . . . . . . . . . 32
       5.11  Debugging . . . . . . . . . . . . . . . . . . . . . . . . 33
       5.12  Environmental . . . . . . . . . . . . . . . . . . . . . . 34
       5.13  Preprocessing . . . . . . . . . . . . . . . . . . . . . . 35

       Appendix I -- Summary of Evaluable Predicates . . . . . . . . . 36



       Errata for C-Prolog User's Manual, Version 1.5
       
       Page  Description
       ----  -----------
       23    Undocumented predicate "append(F)" for appending to files
             should appear here.
       
       24    Example should be X = 3, not X = 5.
       
       25    Symbol for integer bitwise disjunction is "\/".
       
       25    Note left-shift is zero-fill, right-shift is fill with
             value of leading bit.
       
       26    Symbol for X numerically not equal to Y is "=\="
       
       32    Undocumented predicate current_op(Priority, Type, Name)
             should appear here.
       
       36    atomic(T) true for atom, number or DB reference.
       
       --    There are two more undocumented evaluable predicates:
             c([Head | Tail], Head, Tail)  (like Lisp cons) and
             length (List, N) to get length of list.



C-Prolog Predicate Index

Predicate              Page Description
---------              ---- -----------
abolish(F,N)             31 Abolish the procedure named F arity N.
abort                 6, 34 Abort execution of the current directive.
* append(F)              23 open file F to be appended to.
arg(N,T,A)               28 The Nth argument of term T is A.
assert(C)                31 Assert clause C.
assert(C,R)              31 Assert clause C, ref. R.
asserta(C)               31 Assert C as first clause.
asserta(C,R)             31 Assert C as first clause, ref. R.
assertz(C)               31 Assert C as last clause.
assertz(C,R)             31 Assert C as last clause, ref. R.
atom(T)                  27 Term T is an atom.
atomic(T)                27 Term T is an atom, number, or DB reference.
bagof(X,P,B)             29 The bag of Xs such that P is provable is B.
break                 6, 34 Break at the next procedure call.
* c(L,H,T)               26 List L has head H and tail T (Lisp cons).
call(P)                  28 Execute the procedure call P.
clause(P,Q)              31 There is a clause, head P, body Q.
clause(P,Q,R)            31 There is an clause, head P, body Q, ref R.
close(F)                 22 Close file F.
compare(C,X,Y)           30 C is the result of comparing terms X and Y.
consult(F)               22 Extend the program with clauses from file F.
cputime                  25 CPU time since C-Prolog was started, in seconds.
current_atom(A)          32 One of the currently defined atoms is A.
current_functor(A,T)     32 A current functor is named A, m.g. term T.
* current_op(P,T,A)   8, 32 A current op is named A, of type T, priority P.
current_predicate(A,P)   32 A current predicate is named A, m.g. goal P.
db_reference(T)          27 T is a database reference.
debug                17, 33 Switch on debugging.
debugging            17, 34 Output debugging status information.
display(T)               23 Display term T on the terminal.
erase(R)                 32 Erase the clause or record, ref. R.
erased(R)                33 The object with ref. R has been erased.
expanded_exprs(O,N)      26 Expression expansion if N=on.
expand_term(T,X)         35 Term T is a shorthand which expands to term X.
exists(F)                22 The file F exists.
fail                     27 Backtrack immediately.
fileerrors               22 Enable reporting of file errors.
functor(T,F,N)           27 The top functor of term T has name F, arity N.
get(C)                   23 The next non-blank character input is C.
get0(C)                  23 The next character input is C.
halt                      6 Halt Prolog, exit to the monitor.
heapused                 25 Heap space in use, in bytes.
instance(R,T)            33 A m.g. instance of the record ref. R is T.
integer(T)               27 Term T is an integer.
Y is X                   26 Y is the value of arithmetic expression X.
keysort(L,S)             30 The list L sorted by key yields S.
leash(M)             17, 33 Set leashing mode to M.
* length(L,N)            26 List L is of length N.
listing                  32 List the current program.
listing(P)               32 List the procedure(s) P.

* undocumented



Predicate              Page Description
---------              ---- -----------
name(A,L)                28 The name of atom or number A is string L.
nl                       23 Output a new line.
nodebug              17, 33 Switch off debugging.
nofileerrors             22 Disable reporting of file errors.
nonvar(T)                27 Term T is a non-variable.
nospy Spec           18, 33 Remove spy-points from the procedure(s) P.
not(P)                   26 see \+ P, below.
number(T)                27 Term T is a number.
op(P,T,A)             8, 34 Make atom A an operator of type T precedence P.
primitive(T)             27 T is a number or a database reference
print(T)                 23 Portray or else write the term T.
prompt(A,B)              34 Change the prompt from A to B.
put(C)                   23 The next character output is C.
read(T)                  23 Read term T.
reconsult(F)             22 Update the program with procedures from file F.
recorda(K,T,R)           32 Make term T the first record under key K, ref. R.
recorded(K,T,R)          32 Term T is recorded under key K, ref. R.
recordz(K,T,R)           32 Make term T the last record under key K, ref. R.
rename(F,G)              23 Rename file F to G.
repeat                   27 Succeed repeatedly.
retract(C)               31 Erase the first  clause of form C.
save(F)               5, 34 Save the current state of Prolog in file F.
save(F,When)             34 Like save(F), but When says how returned.
see(F)                   22 Make file F the current input stream.
seeing(F)                22 The current input stream is named F.
seen                     22 Close the current input stream.
setof(X,P,B)             29 The set of Xs such that P is provable is B.
sh                       35 Start a recursive shell
skip(C)                  23 Skip input characters until after character C.
sort(L,S)                30 The list L sorted into order yields S.
spy Spec             18, 33 Set spy-points on the procedure(s) P.
statistics               35 Display execution statistics.
system(S)                34 Execute command S.
tab(N)                   23 Output N spaces.
tell(F)                  22 Make file F the current output stream.
telling(F)               22 The current output stream is named F.
told                     22 Close the current output stream.
trace                17, 33 Switch on debugging and start tracing.
true                     26 Succeed.
var(T)                   27 Term T is a variable.
write(T)                 23 Write the term T.
writeq(T)                23 Write the term T, quoting names if necessary.



Predicate              Page Description
---------              ---- -----------
'LC'                 11, 34 The following Prolog text uses lower case.
'NOLC'               11, 34 The following Prolog text uses upper case only.
P,Q                      26 P and (then) Q.
P;Q                      26 P or (else) Q.
P -> Q ; R               27 if P then Q else R.
P -> Q                   27 if P then Q else fail.
!                    14, 26 Cut any choices taken in the current procedure.
\+ P                     26 Goal P is not provable. (i.e., not(P) ).
X^P                      29 There exists an X, such that P is provable.
X+Y, X-Y, X*Y, X/Y       24 Addition, subtraction, multiplication, division.
X//Y                     24 Integer division
X mod Y                  24 X (integer) modulo Y
-X                       25 Unary minus
X^Y                      25 Involution
X/\Y                     25 Integer bitwise conjunction
X\/Y                     25 Integer bitwise disjunction
X<<Y                     25 Integer bitwise left  shift of X by Y places
X>>Y                     25 Integer bitwise right shift of X by Y places
\X                       25 Integer bitwise negation
mathematical functions:  25 exp,log,log10,sqrt,sin,cos,tan,asin,acos,atan,floor
X<Y                      26 As numbers, X is less than Y.
X=<Y                     26 As numbers, X is less than or equal to Y.
X>Y                      26 As numbers, X is greater than Y.
X>=Y                     26 As numbers, X is greater than or equal to Y.
X=:=Y                    26 As numbers, the values of X and Y are equal.
X=\=Y                    26 As numbers, the values of X and Y are not equal.
X=Y                      26 Terms X and Y are equal (i.e. unified).
T=..L                    28 The functor and args. of term T comprise list L.
X==Y                     30 Terms X and Y are strictly identical.
X\==Y                    30 Terms X and Y are not strictly identical.
X@<Y                     30 Term X precedes term Y.
X@=<Y                    30 Term X precedes or is identical Y.
X@>Y                     30 Term X follows term Y.
X@>=Y                    30 Term X follows or is identical to term Y.
[Car|Cdr] or [1,2,3]      7 As a term, a list ( [] is the null list.)
.(Car, Cdr)               7 As a term, a list, de-sugared
[F1,F2,...]           3, 22 Perform the   consult(s) for files F1, F2,..
[-F1,-F2,...]         3, 22 Perform the reconsult(s) for files F1, F2,..
[X]                      26 Evaluates to X, if X is an integer.



                          C-Prolog syntax

       Meta-symbols:
 
       {} for grouping, | for "or", /* for comments */
       * for 0-n occurences, ? for 0-1, + for 1-n
 
       ----- micro-level -----
 
       term            = constant | variable | compound-term
       constant        = number | atom
       number          = sign? digit+ rest-of-number
       sign            = plus | minus
       atom            = atom-character character* 
                         | single-quote character+ single-quote
       atom-character  = lowercase-letter | most-special-characters
       variable        = named-variable | anon-variable
       named-variable  = uppercase-letter character*
                         | underline character+
       anon-variable   = underline
       compound-term   = functor arg-list | operator-expr
                              /*  User-defined or built-in.
                                  Some of the built-ins are
                                  arithmetic, not logical.  */
       functor         = atom
       arg-list        = (argument {, argument}* )
       argument        = term
       operator-expr   = prefix-op | postfix-op | infix-op
       prefix-op       = operator argument
       postfix-op      = argument operator
       infix-op        = argument operator argument
       operator        = functor    /* see page 9 for built-ins */

       ----- macro-level -----

       program         = clause+
       clause          = {positive-clause | negative-clause} period
       positive-clause = unit-clause | nonunit-clause
       unit-clause     = head
       head            = literal
       literal         = predicate arg-list?
       predicate       = functor
       nonunit-clause  = head body
       body            = :- disjunct {; disjunct}*
       disjunct        = conjunct {, conjunct}*
       conjunct        = goal
       goal            = literal | (clause)  /* can nest with parens */
       negative-clause = query
       query           = body
       (or directive)
 
 
       procedure for P = set of clauses for whose head the functor is P



       Prolog data types form a half-lattice:


                                 term
                                 /  \
                                /    \
                               /      \
                              /        \
                             /          \
                            /            \
                           /              \
                       nonvar            simple
                        /  \              /  \ 
                       /    \            /    \ 
                      /      \          /      \
                     /        \        /        \ 
                    /          \      /          \
                   /            \    /            \ 
                  /              \  /              \
              literal           atomic             var 
               /  \           (constant)            |\
              /    \            / | \               | \
             /      \          /  |  \              |  \
            /        \        /   |   \             |   \
       compound       \      /    |    \            |    \
         term          \    /     |     \           |     \
                        \  /      |      \          |      \
                        atom   number   DB-ref    named  anonymous
                                 / \
                                /   \ 
                               /     \
                              /       \ 
                          integer    float

-------------------------------
End of PROLOG Digest
********************