bts@unc.UUCP (Bruce Smith) (05/14/86)
I picked up the following from Arity's bulletin board, and I'm posting
it to 'net.lang.prolog', with their permission. Clearly Arity is not an
impartial observer, and parts of the review-- e.g. comparisons between
Turbo Prolog and Arity Prolog-- may sound like advertising. However, we
are mostly mature adults, here on the net, and we can deal with such
things. Overall, I found it interesting reading, and I hope there will
be some comments from people who've tried Turbo Prolog.
_____________________________________________________
Bruce T. Smith Dept. of Computer Science
USENET: decvax!mcnc!unc!bts New West Hall (035-A)
Others: bts.unc@CSNET-RELAY Chapel Hill, NC 27514
==========================================================
==========================================================
Notes on Turbo Prolog -- Part 1 Peter L. Gabel May 4, 1986
1.0 Introduction
Borland's Turbo Prolog may be "turbo" but it isn't Prolog.
Borland in its attempt to produce a fast in-core compiler for Prolog has made
certain design choices that severely impact fundamental assumptions about the
philosophy of Prolog programming and the structure of Prolog code.
Many problems that are elegantly solved in standard Prolog must be "hacked"
together in Turbo Prolog because of the limited data types allowed. That is,
the data typing system in Turbo Prolog precludes many standard Prolog programs
from executing without major rewriting, usually at a loss of program clarity
and maintainability.
Further, those deviations to Prolog that have been made by Borland make Turbo
Prolog an extremely weak language for symbolic processing and AI. Turbo Prolog
is suitable for conventional programming problems by applying a Prolog-ish
style of declaritive programming to a Pascal-ish data typing system. It is not
at all clear that Turbo Prolog is superior to conventional programming
languages such as C, Pascal or Basic for conventional applications.
The central problem for Arity posed by Turbo Prolog is that neophyte
programmers may believe that this is what Prolog/symbolic programming/AI is all
about and may become turned off without further investigation. This problem is
intensified by Borland's unfounded claims and outright misrepresentations
about Turbo Prolog.
Turbo Pascal put fun into Pascal programming; Turbo Prolog takes the fun of
Prolog programming away.
You can call a pig a horse, but you still can't get it to run in the Kentucky
Derby.
An analysis of Turbo Prolog follows which covers the following areas:
- the Turbo Prolog programming environment
- the core Turbo Prolog language (i.e. the syntax and semantics
of the defined language) and why it differs from Prolog
- the available evaluable predicates and how they differ from
Clocksin and Mellish standard predicates
In addition, the following questions are addressed:
- why did Borland deviate from Prolog?
- how do the deviations limit Turbo Prolog?
- what advantages do the deviations bring?
- what is a neophyte going to think about Turbo Prolog? an expert?
- what is Borland going to do next?
Appendicies to this document include sample Turbo Prolog and standard Prolog
code comparisons as well as benchmark data.
2.0 An analysis of the Turbo Prolog programming environment
The Turbo Prolog programming environment is a window-oriented system
containing:
1) A built-in editor (same as in Turbo Pascal) with functions similar to
Wordstar. The editor is adequate for writing and modifying code; it is not a
syntax-driven editor. The editor is entered whenever a compiler error occurs
with the cursor positioned at the point of error. A stupid problem with the
system is that compiler error messages are truncated within the bottom line of
the edit window and are often unreadable.
2) A compiler (that can compile in-core or to an obj file) The compiler is NOT
incremental despite Borland's claims, all compilations are from the top.
Modularity is supported by special global declarations and "project files".
Modularity requires a common symbol table implying that all modules must be
compiled whenever a single module changes. (Boo hiss.)
The compiler is comparable in speed to the Arity compiler.
The compiler may be invoked to produce exe files; this is actually a finesse.
The compiler produces an obj file and then invokes the Microsoft linker. The
system may not have enough memory for linking large programs without leaving
Turbo Prolog.
It is possible to incorporate code written in Asm, C, Pascal and Fortran. The
data typing system allows very easy interface to external routines. This is a
plus for Turbo Prolog. On the other hand, it is not possible for external
routines to call a Turbo Prolog predicate or for the external routine to do
complex structure hacking such as what is supported in Arity/Prolog.
The compiler's error messages are occasionally very obscure. The section in
the manual concerning error messages does not elaborate beyond the actual text
of the message. Some of the messages are inappropriate, e.g., if you try to
assert a term with unbound variables you get a message "Free variables are not
allowed in WRITE."
3) A trace facility. A window for a trace is provided. This is not a full
debugger. There are two trace options: normal which suppresses TRO and
shorttrace which does not. The edit window allows tracing of source code. This
is actually pretty neat. However, it is severely faulted in not allowing for
the usual spy points and leaping, and useful information is missing such as
invokation number and depth. This means that the tracing facillity is
completely inadequate for debugging large programs.
4) Windows for dialog I/O and messages from the compiler and a menu system with
various pop-up boxes. In general, the appearence of the screen is attractive.
The major pitfalls are clumsy resizing of the windows and truncated messages
(that disappear if you try to resize the window to read it). Also goals
entered in the dialog box better not contain cuts or there is a bug.
5) A help facility. Provides minimal information but useful for looking up how
to use the editor. With better help text this could be neat.
The compiler allows a fast edit-compile-run cycle. However, the lack of an
adequate debugger, and worse, no interpreter for the usual highly interactive
kind of experimentation severely impacts the programming environment. Often
you want to try out code fragments in Prolog as you write a program. Turbo
Prolog hinders such interaction.
To its credit, the overall impression of the programming environment is that it
is slick with a powerful windowing system. What it has in slickness it lacks
in power for interactive development.
3.0 The core Turbo Prolog language.
Turbo Prolog requires all predicates and all forms of terms that are arguments
to predicates to be declared at compile-time. This is NOT optional. This
means that all metalogical operations and predicates that can build new forms
of terms at runtime are not found in Turbo Prolog. No reader. No functor, arg
or univ. No =, \=, ==, \==. Even worse is the fact that there is no way to
declare certain forms of terms at all in Turbo Prolog. For example, you can't
have the following lists: [1,a], [1,[1,2]], [1, 2.0], [1, foo(2)]. And many
programs that require complex data structure manipulations have to be hacked
together because the natural way of defining terms in standard Prolog doesn't
exist in Turbo Prolog.
Thus, Turbo Prolog doesn't do what you fundamentally want to do with a
symbolic programming language: process general symbolic data structures and
generate new structures at run-time. Pattern matching is restricted and
unification in general is broken. The type declarations allow the compiler to
do simple assignment or equality tests in place of unification (which for those
cases where appropriate allows the compiler to generate faster executing code)
but at a huge expense in ease of programming and in generality. Many programs
that are easy to read in standard Prolog cannot run without major
modifications if they can run at all in Turbo Prolog. And the beauty of
Prolog is lost.
3.1 Domain and predicate declarations
The typing system in Turbo Prolog allows new types (domains) to be composed
from the following built-in domains: char, integer, real, string, symbol ( what
is generally called atom), file, and a special ad hoc "database" domain
dbasedom. Another domain is pre-defined for the bios predicate, regdom.
List domains are composed from other domains and are denoted by a star suffix,
e.g., integer*.
The rules of composition of domains are as follows:
1. name = {reference} domain
name1, name2, ... = domain
2. name = {reference} domain*
3. name = f1(d11 .. d1N) ; f2(d21 .. d2M) ; ...
where all functors must be unique
4. file = name ; name; ...
(all files for processing must be pre-named) (boo hiss)
The "reference" keyword is required if predicates using a domain may have out
arguments which leave free variables in terms. This forces the compiler to
generate dereferencing code.
Predicate declarations are of form: pred(d1 .. dN) pred(...)
A predicate may be declared more than once for different domains.
All "database" usage must be declared at compile-time and the only allowed
domains are fully instantiated facts.
This is not a sufficient type system and worse it is static: no domains, atoms
(what they call symbols) or functors may be defined at runtime. This means
that the only symbolic problems that may be solved by Turbo Prolog are those
that have a static, limited set of forms. The Zebra problem is solvable in
Turbo Prolog. Naive Reverse of certain lists may be solved. But even Naive
Reverse of the following list is impossible: [1, foo, 1.2, foo(1), [1,2], X].
3.2 The "dynamic database"
Turbo Prolog's "database" is not a database at all and I cannot see anything
dynamic about it. This is an area where Prolog has such a rich tradition in
both an effective mechanism for the storage and runtime modification of
interpreted code and the storage of arbitrary Prolog terms.
In Turbo Prolog this heritage is obliterated. You must declare the form of
what is to be stored in the "database" at compile-time. You can only store
ground terms (i.e. no free variables). All stored terms are sequentially
accessed and are stored in the heap. This is totally useless for all but toy
applications.
Turbo Prolog provides five "database" predicates: asserta/1, assertz/1,
consult/1, save/1 and retract/1. In all cases, only ground terms (facts) are
handled. Just a shadow of real Prolog's assert and retract.
3.3 Unification and strong equality
The "=" predicate does not exist. You must define equal(X,X) with appropriate
domain declarations to get any semblance of unification. Garbage.
You must define strong equality by using the metalogical predicates free/1 or
bound/1 (the Turbo incompatible equivalents of var/1 and nonvar/1). Again, you
are still constrained by static domain declarations.
3.4 Lack of a Prolog reader (no read/1 predicate)
Because all domains are static and a Prolog reader may allow the definition of
new functors, etc. they just threw it out. They didn't even do the next best
thing: a lisp-ish list reader. This is amazing. No operator precidence
parsing done for you. No DCGs for natural language. No Prolog.
3.5 Evaluable Predicates
Evaluable predicates return values by ASSIGNMENT not by unification. This
means that you must do extra work in the code if you are checking a value.
Again, this just isn't Prolog. This allows the compiler and the runtime system
to make certain assumptions which may speed execution slightly, but at a loss
of generality. This wouldn't be such an issue if you could do real unification
or even strong equality. In practice not a big issue.
3.6 Lack of a garbage collector and "unsafe" memory management (not strictly a
language issue).
The current implementation of Turbo Prolog does not contain a garbage
collector. All structures, strings, reals and "database" items are in a heap
that is addressed with 32 bit addresses. Borland does a good job with TRO and
the data typing helps dramatically with storage consumption but many programs
will still abend with no remaining heap when they could have run if a garbage
collector was present.
Turbo Prolog also acts incorrectly without warning if the stack or trail
overflows. One of the reasons why Turbo Prolog executes quickly is that it
doesn't bother to test for overflows. Usually the system just appears to have
a predicate fail -- you don't know whether that is correct behaviour or not.
3.7 Restrictions on names of user defined predicates
Predicates may not have the same names as built-in predicates even if they have
different arities. Further, user defined predicates must have unique names,
you can't have both foo/2 and foo/3. Not a big deal but a small gotcha.
3.8 Lack of general prolog clause structure.
Turbo Prolog also restricts the use of disjunction (;) to the top level of a
clause. For example, the following clause is illegal in Turbo Prolog:
foo :- goal1, (goal2 ; goal3). Most Prolog programs can be restructured
relatively easily to cope with this at the expense of making the program less
readable.
4.0 Built-in evaluable predicates
There is a total disregard by Borland for the Clocksin and Mellish standard.
And, of course, except for a well developed set of screen handling predicates,
Turbo Prolog is a mere shadow of Arity/Prolog.
The following is a comparison of C & M Prolog with Turbo Prolog.
Clocksin and Mellish Turbo Prolog
---------------------------------------|---------------------------------------
consult consult -- ground facts only
reconsult NA
list notation for consult NA
true NA
fail fail (same)
var/1 free/1
nonvar/1 bound/1
atom/1 NA
integer/1 NA
atomic/1 NA
listing/1 NA (but has built-in editor)
clause/2 NA
asserta/1 asserta/1 -- ground facts only
assertz/1 assertz/1 -- ground facts only
retract/1 retract/1
functor/3 NA
arg/3 NA
=.. (univ) NA
name/2 NA -- but includes five predicates
for type conversion: char_int,
str_char, str_int, str_real,
upper_lower
! !
repeat NA (but easily defined)
, , and
; ; or
call/1 NA -- major missing feature
not/1 not/1
= NA
\= NA
== NA
\== NA
get0/1 readchar/1
get/1 NA
skip/1 NA
read/1 NA -- major missing feature!!!
put/1 NA
nl nl
tab/1 NA
write/1 write/? -- bizzare multi-arity
version
display/1 NA -- but there is a predicate by
the same name for writing strings
op/3 NA
see,seeing,seen,tell,telling,told an equivalent set but non-standard
names also has seek abilities
X is Y, arithmetic comp preds X = Y, but only evalutes expressions
at compile time; also has arithmetic
comparison predicates; handles reals
and various trancendental functions;
comparison preds are oveloaded for
symbols and strings
Additional predicates contained by Turbo Prolog are: 1) various data typed I/O
predicates, but no standard read and write. 2) 27 screen handling predicates
for windowing, editing and turtle graphics 3) 5 string handling predicates 4)
findall/3 (worth having) 5) a variety of system predicates for beeping, hitting
interupts and ports, etc
To their credit, Borland did a good job with the screen predicates and have the
minimal string predicates. However, the claim on the back cover of "supporting
a large superset of the Clocksin and Mellish Edinburgh standard Prolog" is a
lie.
Some simple sugars to Prolog are impossible to implement in Turbo Prolog. Most
notable is the DCG formalism which is standard in Arity/Prolog. So much for
natural language processing.
5.0 Issues
5.1 Why did Borland choose to deviate from the standard?
I believe that Turbo Prolog probably started as some student's idea of how to
improve the efficiency of Prolog's execution. The idea is that by avoiding
some of the generality of Prolog where it is not needed one could get much
better generated code. It also might be motivated by trying to make Prolog
more "conventional". It may be the case that Turbo Prolog is more natural to a
garden variety Turbo Pascal programmer than standard Prolog. Indeed, they
might think it's better.
A proper OPTIONAL typing system would improve Prolog. It could both increase
efficiency and potentially improve self-documentation of code and runtime error
trapping. Arity/Prolog currently makes use of mode declarations.
Many programmers believe that explicit type declarations are good. However,
there are vast differences in functional usage of a conventional language
versus a symbollic language. The "Pascalization" of Prolog results from a lack
of insight concerning the needs of a programmer doing symbollic applications.
The propaganda value of the type system may be great for Borland.
5.2 How do the deviations limit Turbo Prolog?
Programs that require any of the following cannot be written in Turbo Prolog:
- a real database
- complex terms
- new types of terms formed at runtime
- term I/O
- metalogical operations
- interpretation of arithmetic expressions at runtime
Most non-trivial programs are uglified by the restrictions forced by the type
system. Programs usually need to be restructured and are less general.
One would think that adding a data type system to a language, even if not
optional, should NOT force a different discipline of programming and break many
quite reasonable programs. Obviously Borland does not choose to see the world
in this way.
5.3 What advantages do the deviations bring?
Programs that are relatively simple and primarily deterministic will run faster
than Arity/Prolog with relatively little pain. The speed difference ranges
from insignificant (or slower for zebra) to 2 times faster for integer naive
reverse (not true naive reverse, by the way) and 3 times faster for sieve of
Erosthenes. More typical programs that are composed of non-deterministic
predicates are slower in Turbo Prolog than Arity/Prolog.
5.4 What is a neophyte going to think about Turbo Prolog? An expert?
Someone who is new to Prolog may get turned off to the language by not
realizing that Turbo Prolog is not Prolog. More probably, they will realize
that Turbo Prolog is just a toy and may get their appetite whetted for a real
Prolog.
An expert is going to see that it is a toy right off.
"Just because it has a compiler doesn't mean that its not a toy."
5.5 What is Borland going to do next?
Go public. Beyond that, they would need to completely re-engineer the product
to fix it. And thats not their style.
So they will spread a tremendous amount of misinformation about Turbo Prolog
and Prolog in general. I'm sure that they will introduce a Turbo Toy expert
system product too.
6.0 Major features of Arity/Prolog not found in Turbo Prolog
- REAL PROLOG: true superset of C & M Prolog
- virtual dbms, arbitrary terms, 1 gigabyte, indexing, partitions
- interpreter and debugger
- modular compilation, ability to add to the interpreter
- lint
- far prolog
- garbage collector
- DCGs
- sophisticated language interfaces
- optional mode declarations
- edit/1
7.0 Planned improvements to Arity/Prolog that are similar to Turbo Prolog
The current development in systems work will subsume any advantages that Turbo
Prolog enjoys in the following areas and will significantly increase
Arity/Prolog execution speed (we already beat them in more typical Prolog
programs).
- screen stuff
- bios/3
- easy C interface
Overall, the advent of Turbo Prolog will not sway mainstream development
efforts for the next version of Arity/Prolog. tfra@ur-tut.UUCP (Tom Frauenhofer) (05/16/86)
[Et tu, line-eater?] A correction: Turbo Prolog DOES support unification using the "=" sign. You do NOT have to define a predicate like "equal (X,X)". FLAME ON The only "lies" I found was calling this :"garbage" a review. Seemed like a sales brochure to me. (I have used Turbo Prolog. It's nice, but it is more like "Let's make Turbo Pascal and call it Turbo Prolog. Wala!"). FLAME OFF Perhaps a more impartial review would be useful? -- Tom Frauenhofer ...!seismo!rochester!ur-tut!tfra "Gosh, if Phillipe Kahn, so Kahn I!"