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