FORTH, PASCAL, and C--- which one would you choose (it depends ?)

Tom Almy toma at tekchips.UUCP
Tue Jan 7 05:08:59 AEST 1986


Normally I don't bother to flame back at flames, but this one has some
errors that I cannot ignore.

In article <681 at pucc-j> rsk at pucc-j.UUCP (Wombat) writes:
>
>There are severe problems with Forth that prevent it from being much more than
>an interesting (failed) exercise in threaded-interpretative language design.
>
>It is (1) compact, (2) modifiable at runtime, (3) extensible and (4) hard to
>read.  Some of these are also features/flaws of other languages, depending on
>your viewpoint. However, I'd like to point out the following:

I fail to see how item (1) could be considered a "flaw", Forth is no more 
modifiable at runtime (2) than most other languages except Pascal, (3) 
is a subjective judgement.

>1. Forth is a lot harder to read than even Lisp or APL; at my former employer,
>where we used Forth in real-time control and number-crunching applications,
>we called it a "write-only" language.

A lot of this has to do with programming style.  It is possible to write
readable Forth code, see the book "Thinking Forth".  And it is also possible
to write unreadable programs in any language.

>2. There are many incompatible implementations of Forth, and even
>implementations from the same vendor behave radically different on
>different processors.

The vendor in question must be Forth, Inc.  They strive to be incompatible
between their implementations.  This is not the case for products of
Laboratory Microsystems, MicroMotion, F83, and even the ancient FIG Forths.

>3. The debugging support is non-existent.

The public domain F83 has an interactive debugger.  A display-oriented
debugger is an option for Laboratory Microsystems IBM-PC product.

>4. The primitive set of operators is *very* large; and it is not orthogonally
>constructed; the names are not even *close* to mnemonic; and many operators
>have uncontrollable side effects outside the modules in which they are used.
>

Unfortunately, true, but most names are mnemonic and quite a few others are
understandable after you know the naming conventions.  For instance "." in a
name always means "print", "?" at the beginning of a name means it does
something conditionally, and "?" at the end of the name means it leaves a
boolean result.

>5. Forth is not structured, typed, or anything like that.  When
>using Forth, you may forget anything you learned from Software Tools, or
>Elements of Programming Style, or Niklaus Wirth, or, roughly speaking,
>the last 15 years of evolution in programming techniques.
>

Well it is structured, at least as far as control structures are concerned.
There are no "gotos".  Provided control structures are:
1. IF statement, with optional ELSE.  Never any ambiguity of association
   between IF and ELSE like in some other languages.
2. DO LOOP structure.  Most implementations have a variation which allows
   skipping the block if it is to be executed zero times.  Loop can count
   up, count down, or count by a varying amount (positive negative or zero
   on any particular iteration).  A command exists to exit a loop in the
   middle.
3. Two iterative structures, one with conditional exit at the end, and the
   other with conditional exit anywhere in the middle.
4. Most implementations have a CASE statement.  For those that don't, it
   can be easily (and in an implementation independent way) be added.

Data structures can be added as desired.

>And now, I'd like to quote another article that appeared at the time:
>
>> From: libes at nbs-amrf.UUCP
>> Newsgroups: net.ai
>> Subject: Forth for AI?  NO!
>> Date: Sun, 22-Jan-84 19:54:16 EST
>> 
>> 1) Manipulating programs as data in Forth is difficult.  Also
>> impractical, since it has no garbage collection.  You can't expect to
>> service high-priority interrupts if you've just run out of space!
>> (Forth's primary use is for real-time control.) 

But this was cited as undesirable in (2).

>> 2) Can't pass arguments explicitly.  You must pass information by
>> putting it on the stack.  Since I pushed the 2nd arg at line 6 and then
>> used the stack to do something else, what are the odds that at line 23,
>> I can push the 3rd arg on the stack and then call that function with
>> confidence?  Reading code, trying to find out what the arguments are, is
>> like counting parens in Lisp, except now imagine that every atom in the
>> list manipulates the count of ('s and )'s! 

You can pass arguments in variables and there are several published techniques
to create named parameters (so they can be accessed without stack
manipulation).  But the biggest flaw here is "line 23".  The proper Forth
programming technique is to have lots of small functions rather than a few
big ones because subroutine calls are cheap.  I have a 5000 line Forth
application, and there is only one function longer than 15 lines and no
more than a dozen longer than ten lines.  Forth code can also be DOCUMENTED
(anybody know what that word means?) with comments as to stack contents.

>> 
>> 3) Forward referencing (including recursion) is not normal and must be
>> done by manipulating compiled code.  Bye-bye portability. Indeed, I have
>> never seen anyone write a recursive Forth routine (although it can be
>> done).  Bye-bye AI. 

True, it is not normal, but it can be done in a portable fashion without
manipulating compiled code.  I have written many recursive Forth routines,
and recursion is *VERY* efficient in Forth.  Also Forth metacompilers and
compiler do allow for forward referencing at the cost of not being 
interactive (in other words "batch").

>> 4) Code is generated as you type (or load) in Forth source.  Hence you
>> lose all possible benefits of a good compiler, i.e. type-checking,
>> optimization, etc.  As for syntax checking, forget it.  The syntax of
>> the language is so simple, almost every combination of Forth words is
>> syntactly correct (although meaningless).  If you mistyped that last
>> word, you'll find out at run-time. 

Control structures are checked for syntatic correctness. Compilers can
do optimizations and produce code quality comparable with that of C or
Pascal.  If you mistype a word you find out right away (assuming that
the word is not a valid Forth word).
 
>> 5) Scoping, name-space rules are terrible.  For example, it is impossible to
>> write a subroutine that uses variables that are *guaranteed* to be local.
>> (How can you ever be confident about your code?) 

You CAN write subroutines that use variables guaranteed to be local (technique
requires writing of three one-line routines which localize the scoping of
selected words (which may not only be variables but also other subroutines).

You can also write code without worrying about redefining existing routines
(no reserved words or function names) since your definitions do not alter
the operation of the existing functions.  Thus if your application were so
brash as to redefine the operation of "+", the Forth nucleus would continue
to use the original version.

>> 
>> 6) The emphasis on Forth is on speed at the cost of everything else. For
>> example, if you can keep track of all data by storing it on the stack,
>> great, but if you have to use a variable (no less a structure) you start
>> losing efficiency.  Using a variable in Forth is akin to using those
>> features in PL/I that are great but really slow the runtimes down.  And
>> Forth simply isn't fast to begin with. Any decent compiler can do better
>> (then "threaded-code"). 

Using variables in Forth is frequently faster than stack manipulation.
Forth compilers can handle variables with the same efficiency as other
compilers.  No Forth programmer will ever claim that threaded-code is faster
than true compilation, but it is faster than other interpreted languages such
as BASIC LISP and Smalltalk.  The use of threaded code allows for very fast
and incremental compilation which greatly reduces the edit-compile-test
cycle time of program debugging.  If the final program is insufficiently
fast, then portions of it can be compiled or rewritten in assembly language.

>> 7) The only messages from the system are "ok", "?" (meaning "I don't
>> know that word") and "stack empty".  (It might check stack-full and some
>> others, but these are the only msgs I've ever gotten.)  This is very
>> consistent with the Forth philosophy (see 6.) but really unhelpful.
>> Debugging note: If Forth encounters a word it doesn't know, the stack is
>> popped.  Since the only other error is when the stack is empty, it is
>> impossible to tell where you died by looking at the stack! 

Again, this looks like Forth Inc.'s product which is very user unfriendly!
Laboratory Microsystem Forth's manual lists 39 error messages.  Forth 
discovers words it doesn't know at compile time, so you know exactly
where the error is.  Most systems do not tell you where you are when runtime
errors occur.  Most systems also provide hooks in the error routines so
that you can do anything you want (including examining the stack).


There are occasions to choose Forth, as well as occasions to avoid it.
I find that I can develop programs far faster in Forth than in C or
Pascal.  But I do use C or Pascal for programs that make heavy use of
data structures (that are directly supported by these languages).  
For character string manipulation I still prefer BASIC. 

Tom Almy



More information about the Comp.lang.c mailing list