[comp.lang.forth] FORTH-83

ir230@sdcc6.ucsd.edu (john wavrik) (07/15/90)

                        IN DEFENSE OF FORTH-83

It would be illuminating if some of the members of the FORTH-83 team 
presented the rationale for their decisions. I was not a member of 
that team, but I have had numerous discussions with its chairman, Guy 
Kelly, about the 83 Standards. 

Disclaimer: The following views are my own. They are based on 
    impressions gained from conversations together with my own 
    experiences with Forth before and after Forth-83.
    
While I do not agree with everything the 83 team did, I also don't 
think their work was entirely as haphazard and incompetent as it is 
currently being portrayed. Here is a summary of the two existing 
Forth standardization efforts:

    The Forth-79 team saw its work as an effort to turn fig-Forth into 
    a Standard. Forth-79 is essentially fig-Forth with only a few 
    modifications [and, unfortunately, omissions].

    The Forth-83 team saw its work as an effort to produce a final 
    "touch up" of Forth. To deal with some inconsistencies and fix the 
    actions of a few words.

The Forth-83 changes that are freshest in mind are those which caused 
changes in code and those which are subjects of current controversy. 
This essay will deal with these. 

LOGIC AND BITWISE OPERATIONS
     The words AND, OR and NOT are part of the English language. They 
are used in common speech in a logical sense.

        If it is NOT raining then we will go to the zoo.

we do not say

        If raining = 0 then we will go to the zoo.

The function of NOT is to change truth value. It is the proper word 
to use for logical statements. 0= is not the proper word here for two 
reasons (1) Semantically we are reversing truth value, not testing a 
number for zero;  (2) The fact that 0= may change truth value is an 
accident of a particular representation for booleans. [In many Forth 
systems the word WHILE is an alias for IF -- but we do not and should 
not use them interchangeably.]

    Around the turn of the century, the English mathematician George 
Boole invented the idea of using numerical representation for logical 
concepts. He found that if TRUE is represented by the number 1 and 
FALSE by 0, statements in logic could be turned into arithmetic 
statements. He developed an algebra of logic. In the early days of 
computer circuitry this proved to be the key to having machines 
perform logical operations. The names AND, OR and NOT for bits come 
from this Boolean transformation of logic to numbers. Eventually 
the words AND, OR, etc. came to be used for operations on bit patterns 
rather than individual bits. The words acquired a second meaning.

     In Forth-79, TRUE was represented by 1 and FALSE by 0. The words 
AND and OR had bitwise meanings but they also worked correctly for 
booleans. NOT, on the other hand, was a synonym for 0= and could only 
be used in the logical sense. It seemed inconsistent, when using bit 
masks, to have AND, OR, XOR function as in assembly language -- but to 
have no equivalent of NOT (the word COM for bitwise complement was 
only in the Reference Word Set). 

     The Forth-83 team discovered that if TRUE were represented by the 
number with all bits set (rather than by 1) then the bitwise NOT would 
also be the logical NOT. We had, in fact, been using the wrong number 
to represent truth value. Once the change is made, everything falls 
into place and the logical/bitwise discrepancy disappears.

[The current discussion of the issue by the ANSI team is bizarre.
Mitch Bradley informs us that everyone agrees to represent TRUE by
all bits set. Once this is agreed on, there is no reason not to use 
NOT. What caused many of us grief in switching from '79 to '83 is that
we did arithmetic on flags. It is poor programming practice to 
confuse numbers and booleans (which includes confusing NOT with 0=). 
Strongly typed languages enforce the distinction. Forth relies on the 
discipline of the programmer.]

MONO-ADDRESSING
    Forth-79 had inconsistencies in operations using addresses. The 
word ' (tic) was state-smart and left the parameter field address. the 
word FIND, on the other hand, was not state-smart and left the code 
field address. EXECUTE used the code field address. To compound the 
problem, the words CFA, PFA etc from fig-Forth were eliminated
(so there was no Standard way to get from one of these addresses to 
another).

    Forth-83 chose to make all operations based on a single address
associated with each word (the "compilation address") [which, in every 
implementation I've seen, is the cfa].

[None of the reports from ANSI have indicated how this difference 
between '79 and '83 is being handled]

STATE-SMART WORDS
    The Forth-83 team felt it objectionable to use the same name for 
two totally different actions. Words like ' which had different 
actions depending on STATE were replaced by a pair ' and [']. 

[None of the reports from ANSI have indicated how this difference 
between '79 and '83 is being handled]

DO..LOOP
    The Forth-79 loop was apparently constructed in the days when 32k 
was considered a lot of memory. LOOP made a signed comparison of the 
loop index and limit. This meant that, for a 16-bit system,
       32800 32600 DO I . LOOP    would print 32600 and stop

[32800 = -32736]

The Forth-83 team redefined DO and LOOP to remove this unusual 
behavior. They also provided a conceptual base (the number circle) for 
understanding how loops operate -- and a consistent "crossing the 
boundary" exit condition for all forms of the LOOP construct. They
also decreed that LEAVE cause an immediate exit from the loop (rather 
than take effect only at LOOP when the test is made).

[None of the reports from ANSI have indicated how this difference 
between '79 and '83 is being handled]

DIVISION
   One source of misunderstanding should be cleared up before going 
further:
    
    Numbers and their arithmetic are not within the domain of 
    computer language teams to define. Some think numbers were 
    created by God -- others by the mathematicians of 
    antiquity. In any case, they exist "out there" and must be 
    treated as given. 

    Computers cannot represent numbers exactly as they are 
    understood in mathematics. Only a subset of the integers
    can be represented. It must be clear to the user which 
    subset is represented and exactly how the arithmetic 
    operations in the language differ from the corresponding 
    operations in mathematics. It is expected that the computer 
    arithmetic will be as close as possible to "real" 
    arithmetic.

In mathematics frequent use is made of the fact that, given any two 
integers a and b (with b not zero) there are integers q and r so that
(1)  a = bq + r   and  (2)  0 <= |r| < |b| .  Algorithms in which this 
occurs can present both positive and negative values of a and b. Often 
only the fact that (1) and (2) are satisfied is important [thus 
however MOD is defined, it is important that / is consistent with it].
There are, however, classes of algorithms in which a particular 
remainder is needed.  When b is positive, the two most important 
choices for r are: 

         a.  0 <= r < b        ( non-negative r )
         b.  -b/2 < r <= b/2   ( smallest magnitude r )

Forth-79 division is "rounded to zero" -- it does not give either of 
these. The use of "rounded to zero" division always required a 
readjustment of the remainder.

The "floored" division in Forth-83 always yields the more useful form 
a. for the remainder. After having used both Forth-79 and 
Forth-83 for a number of years, it is fair to say that the 
Forth-79 division really has no useful mathematical 
properties. It is only an accident of history that it has been 
used. I can't think of a single case where "rounded to zero" 
arithmetic is preferable to "floored". 

[The use of "floored" division is, as far as I'm concerned, just 
another small improvement of Forth over other languages -- and of 
Forth-83 over Forth-79. But here is a personal opinion:

    If there are compelling reasons for going back to the older 
    division, it would be preferable to do that than to have /MOD left 
    implementation dependent.  /  is the symbol everyone uses for 
    division -- and will continue to use. Progress in Forth depends on 
    the ability of people to share code fragments more than complete 
    applications. It will be a great blow to progress if the meaning 
    of very basic words is left floating.]
    
PICK, ROLL
    In applications which require everything to be left on the stack, 
these words can be useful. In Forth-79 these were indexed at 1. In 
Forth-83 they became indexed at 0.

[This is one that I honestly don't understand. Apparently the Forth-83 
people think of the argument as an offset -- so the top of the stack 
is 0 and OVER is 1 PICK.]

Final Comment: My switch to Forth-83 was prompted by a crisis: 
    our courses were being switched to a micro-computer lab 
    and the vendor of the Forth-79 I had used for years for 
    research suddenly turned from Dr. Jekyll to Mr. Hyde. 
    Apparently he intended to finance a trip to Hawaii (for 
    his entire company) on the profits from my course. I vowed 
    henceforth to stick to Microsoft, Borland, or public 
    domain! I quickly acquired F83 and a copy of the Forth-83 
    Standard document. It soon became clear that I had a lot 
    of re-writing to do (being able to run old code using a 
    "prelude" was not good enough -- instructional material, 
    in particular, had to correspond to what was found in 
    books and on the system in use). Updating to a new 
    Standard is not easy -- and, I must admit, I came to my 
    first meeting with Guy Kelly with a chip on my shoulder. 
    After switching, however, I was pleased with F83 and I 
    found that most of the changes made by the Forth-83 team 
    were for the better. I feel that the Forth-83 team left 
    Forth a stronger language. 

    Tweaking the language itself rather than using it to do 
    something is a disease that seems to afflict the Forth 
    community. I do not share the idea that the basic parts of 
    the language should be constantly "under construction". I 
    also feel that any proposed new addition to the language 
    should be implemented on many different systems and tested 
    (by many people) for several years before even being 
    considered for incorporation in a new Standard. Once 
    every 10 years we should meet. We should select the best 
    of the changes and improvements that have been proposed 
    and tested. We should *all* rewrite our systems to comply 
    with the new Standard. And we should use our new found 
    portability to cooperatively build structures larger than 
    the wheel. 

                                                  John J Wavrik 
             jjwavrik@ucsd.edu                    Dept of Math  C-012 
                                                  Univ of Calif - San Diego 
                                                  La Jolla, CA  92093 

peter@ficc.ferranti.com (Peter da Silva) (07/16/90)

In article <11887@sdcc6.ucsd.edu> ir230@sdcc6.ucsd.edu (john wavrik) writes:
> STATE-SMART WORDS
>     The Forth-83 team felt it objectionable to use the same name for 
> two totally different actions. Words like ' which had different 
> actions depending on STATE were replaced by a pair ' and [']. 

From rumors around at the time, basically Chuck Moore found state-smart
words objectionable and convinced enough other people to get this through.
Chuck Moore's own product, PolyForth, was pretty primitive... and the lack
of state smart words and nesting checking for BEGIN/IF/DO were the worst
part of it.

My own reaction to dropping state-smart words was negative, to say the
least. You quibbled over the semantics of NOT (I happen to agree with
you there, by the way) based on human factors. Well, human factors argue
for making the same word have the same semantics whether in compile
state or interpret state. {." foo"} should no more have to be changed
in a definition than {3 .}.

Fixing DO loops and removing the conflict between {'} and {-find} were
pretty nice features. I much prefer floored division. A lot of the F83
changes were positive... though the cosmetic changes (for example, from
-dup to ?dup) seemed pretty arbitrary. But getting rid of state-smart
words was a distinct step backwards in the name of purity.
-- 
Peter da Silva.   `-_-'
+1 713 274 5180.
<peter@ficc.ferranti.com>

ForthNet@willett.UUCP (ForthNet articles from GEnie) (07/18/90)

In <GIP4+J3@xds13.ferranti.com>, peter@ficc.ferranti.com (Peter da Silva) writes:

> My own reaction to dropping state-smart words was negative, to say the
> least. You quibbled over the semantics of NOT (I happen to agree with
> you there, by the way) based on human factors. Well, human factors argue
> for making the same word have the same semantics whether in compile
> state or interpret state. {." foo"} should no more have to be changed
> in a definition than {3 .}.

Ok, I'm a novice at the trickier aspects of Forth.  If {'} is STATE-SMART,
then the sequence ' CREATE will behave the same when compiled as when
interpreted (leave some kind of address related to CREATE on the stack)?

If you have that, then you need some OTHER word which can be compiled
and when executed will put the address of the word next found in the
input stream onto the stack.  As I see it you still need two words.  It
seems cleaner and simpler, to me, to have two state-less words that one
state-smart word and another one that is state-less (but only used in
definitions?).  I think I can see the point of your analogy with {3 .}.
My reply to that is that the analogy is based on a flaw.  The flaw (IMO)
is that you should look at {'} *not* as a word that reads the word
following it in the input stream at the point the ' occurs, but rather
as a word that reads the next word in the input stream when it is executed.

I find your position on state-smart words rather puzzling because it
seems to me that Forth normally goes out of its way to be simple and
transparent.  State-smart-ness, to me, says that Forth is smarter and
knows more about what the programmer wants than the programmer does;
i.e. the programmer is too dumb to understand the difference between
interpreting and compiling.

I hope that I haven't just set up a straw man in order to knock it down.
I must be misunderstanding something somewhere, but don't know what yet.

-Doug
-----
This message came from GEnie via willett through a semi-automated process.
Report problems to: uunet!willett!dwp or willett!dwp@hobbes.cert.sei.cmu.edu