Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!mailrus!cs.utexas.edu!uunet!murtoa.cs.mu.oz.au!munnari.oz.au!cs.mu.oz.au!ok
From: ok@cs.mu.oz.au (Richard O'Keefe)
Newsgroups: comp.lang.prolog
Subject: Re: logic programs -> procedural lang?
Summary: red herring
Keywords: Prolog, typing, compiler efficiency
Message-ID: <2181@munnari.oz.au>
Date: 25 Sep 89 04:47:37 GMT
References: <27335@shemp.CS.UCLA.EDU> <869@gamera.cs.utexas.edu> <10822@eerie.acsu.Buffalo.EDU>
Sender: news@cs.mu.oz.au
Lines: 118

In article <10822@eerie.acsu.Buffalo.EDU>, axaris@cs.buffalo.edu (Vassilios Axaris) writes:
> I have been surprized when I first got my Turbo Prolog compiler, in that I was
> required to specify the type of objects being used.

In short, you were surprised to discover that what you got was NOT a
Prolog compiler, but a compiler for another (closely related, but still
OTHER) language.

Whenever I hear that someone is thinking of getting Turbo Prolog, I tell
them to look first at Trilogy.  If you are willing to use a sort of
Prolog/Pascal hybrid (Turbo Prolog), you ought to be happy with a logic
programming language which is not a Prolog/Pascal hybrid but was designed
from the start to let you do the kinds of things that Pascal is good for
in a clean logic programming way.  I have a copy of Trilogy, and while
it's somewhere between two other countries at the moment, I was favourably
impressed by it, and would prefer Trilogy to Turbo any day of the week.

> Later, I realized that even
> though this was putting a burden on the programmer, as well as deviating from
> the standard, it could be (as it was I believe) useful in minimizing the runtime
> type checking of the objects, in Common Lisp manner.

You should be aware that there are Prolog systems for the PC which can
run rings around Turbo Prolog, *without* sacrificing compatibility.  I'll
let the vendors tell you which ones.

Basically, "run time type checking" is a red herring for Prolog.
Consider something like
	append([], L, L).
	append([H|T], L, [H|R]) :-
		append(T, L, R).
In Pascal terms, this would be
	type
	    listPtr = ^listRrec;
	    listTag = (kNil, kCons);
	    listRec = record case tag: listTag of
			kNil: ();
			kCons: (head: something; tail: listPtr);
		      end {listRec};

	function append(A, Z: listPtr): listPtr;
	    begin
		case A^.tag of
		    kNil:	append := Z;
		    kCons:	append := mkCons(A^.head,
						 append(A^.tail, L));
		end {case};
	    end {append};

The 'case' statement in the Pascal program is the equivalent of the
'indexing' done in Prolog.  No amount of type checking at compile time
is going to eliminate that 'case' statement.  But that's where the
"run-time type checking" is happening in the Prolog system.

To be sure, tagging does slow arithmetic down.  Static typing can help
there, *IF* you also have strict mode checking as well.  However, if
arithmetic is more than say 30% of the cost of your Prolog program,
you aren't doing things the Prolog Way.

Lisp needs types much worse than Prolog, because the Lisp equivalent
of append/3 would be
	(defun app (A Z)
	    (if (endp A)			; check A
		Z
		(cons (car A)			; check A again
		      (app (cdr A)		; check A again
			   Z))))    
where A gets checked three times.  In the code produced by a good Prolog
compiler, this effectively happens just once, and is ``paid for'' by the
`if'.  See
    Author:  David H.D. Warren, Luis M. Pereira
    Title:   Prolog: the language and its implementation compared with Lisp 
    Journal: Proceedings of the Symposium on Artificial Intelligence
	     and Programming Languages
    City:    University of Rochester
    Date:    August 1977
    Pages:   109-115
    Other:   published as SIGPLAN Notices 12:8 and as SIGART Newsletter 64

> In today's RISC world, I
> think it would be very useful to include such declarations to aid the compiler
> in creating efficient code, by minimizing tag processing. 

Hang on a minute, Turbo Prolog runs on 80*86s, which aren't RISCs...

Real Prologs (as opposed to Turbo[*] Prologs) let you pass variables around
in a way which requires run-time tests ANYWAY in order to tell whether a
variable is instantiated or not; given that, any other tag checking that
may be required comes free.  Advanced Prologs (SICStus Prolog, NU Prolog,
I believe ECRC though I haven't tried it, CHIP, CLP(-)) allow variables
to be ``constrained'', which also requires run-time checks in the course
of which other tag checks come free.

[*] ``Turbo'' is a Latin word meaning ``I swirl [things] around,
make [things] confused.''  A ``turba'' is a mob.

> How does the Prolog community feel about such an addition? Is it reasonable to 
> do it for the sake of improved execution speed on workstation type environments?

Today's good Prolog compilers on today's workstations already produce fast
code, to the point where you might write C or Fortran code for number-
crunching or interfacing to existing libraries, but would not be tempted to
rewrite your program as such in C.  (Unless you have written very bad Prolog
code.)  Don't make the mistake of thinking that types are necessary for
efficiency:  BCPL, BLISS, and many other systems programming languages are
not typed.

However, type checking *IS* useful for detecting mistakes in programs,
and types are useful when designing a program.  As far as I know,
Bruynooghe was the first to write about types in Prolog.  But there is
a large and growing literature on type checking and type inference in
logic programs.  The NU Prolog Debugging Environment (spelled NUDE,
apparently pronounced `nood') includes a rather powerful type checker.
The source code of the Mycroft & O'Keefe type checker was posted to this
news group a year or so ago.  [Sorry, playmates, but there is a mistake
in it.  It treats disjunctions as if they were conjunctions.  This
usually doesn't matter, but occasionally it will reject a disjunction
which is in fact well typed.]