[comp.lang.forth] Parameter Lists

DAVID@PENNDRLS.BITNET (12/06/88)

While I was waiting for the Pressman book to get to me through
inter-library loan, I found one of the software design books recommended
by someone else (I don't know who):

  Structured Design: Fundamentals of a discipline of Computer
    Program and systems Design, Edward Yourdon and Larry L Constantine,
    Prentice-Hall, Englewood Cliffs, New Jersey, 1979

This book is several years old, so it stresses concepts that have been
superceeded or amplified by more recent work (see the Pressman book),
but it certainly does contain some food for thought. A lot of the basic
concepts are echoed by Brody in Starting Forth, but there is more about
*why* the ideas are good, which is very useful.

For example, let's return to the question of argument lists for a
moment.

Constantine and Yourdon agree with Fraser in favoring parameter lists.
The argument in favor of parameter lists is based on the concept of
``complexity''.  The less complex a program is, the easier it is
for the programmer to comprehend it, the fewer bugs he will introduce
during initial coding and the easier it will be to fix bugs later.

Speaking of the subroutine call interface, the interface is less
complex if:

  * the information (represented by the call) can be accessed
    directly by the programmer (e.x.: no indirect data types.)

  * the information is presented locally (e.x.: parameter lists).

  * the presentation is standard (e.x.: input args first, output second).

  * its nature is obvious (e.x.: intuitive subroutine names(?)).

They then present several example subroutine calls, ranging from
the completely explicit [CALL LENGTH(x0,y0,x1,y1,distance)] to the
completely implicit [CALL LENGTH].  There is a point to each example,
but I am concerned here only with the difference between the first
and last.

Before I go on, I should also mention that another measure of complexity
is the sheer number of keystrokes involved in the construct.  The more
keystrokes, the more chances for a ``finger-check''.  Of course,
finger-check ``bugs'' are considerably less significant than run-time
bugs.

Yourdon and Constantine argue that the completely explicit call form is
best, since it meets the four criterion outlined above.  In discussing
(and rejecting) the implicit form, the authors say this:

  Finally, we consider (the implicit case), which suggests an
  interface of CALL LENGTH. At first glance, it may appear that such
  a subroutine call has *no* parameters -- but we know better.
  LENGTH still requires initial (X,Y) coordinates and final (X,Y)
  coordinates to perform its task, and it must still leave the
  DISTANCE information where that information will be stored. The
  problem is that the programmer doesn't know -- at least, not by
  looking at the statement CALL LENGTH. In other words, the
  parameters are not *local* to the subroutine-calling statement;
  all the information is provided *remotely*, in a place whose
  whereabouts cannot be determined by looking at the CALL LENGTH
  statement.

  If all the arguments were set up immediately preceding the call to
  LENGTH, it would be obvious. However, it is hardly safe to assume
  that all programmers using the CALL LENGTH statement will adhere
  to such discipline. Eventually, the programmer begins taking
  advantage of the fact that some of the parameters naturally are
  set up 23 statements earlier in the code.

These arguments are fine, but they reflect an obvious traditional
language bias.  The subroutine call as it would appear in FORTH,
LENGTH, is not referring to ``remote'' arguments; the arguments
are all right there on the stack, and indeed must have been set up
just prior to the call to LENGTH.  (This is implied by the shortness
of FORTH words.) The FORTH form also involves far fewer keystrokes
and thus fewer opportunities for initial error. The FORTH call does,
however, still fail the explicitness test (Fraser's argument), and so is
inferior to the explicit form in terms of overall complexity.

So, it would seem that explicit parameters win the day.  But not, I would
claim, by much.  With my modification to Yourdon and Constantine's
argument, the FORTH form of the call would appear to be a close second
best call format out of the selection they discuss.  It fails only
because it does not show the arguments completely explicitly, but
instead depends on the debugging programmer reading the entire word
and keeping track of the three deep stack in his head.  This is an
important deficiency *all other things being equal*.

As Yourdon and Constantine themselves point out, there are many factors
that enter into the complexity problem.  One is the fact that the FORTH
call format takes fewer programmer keystrokes.  (In the project I am
currently working on, almost all of my ``compile time'' errors have been
simple syntax/typos in subroutine call argument lists.) A second was
mentioned already by another poster: the FORTH format gives the
debugger more immediate access to the *algorithm* realized by the code
(when there are no FLIP FLOP PLOPs) and this is a very important
reduction in complexity. (Obviously, there is a tradeoff here.  See
below for my ``solution''.) Yourdon and Constantine also report that the
human mind does not handle more than seven distinct simultaneous objects
or more than three simultaneous levels of nesting. By the same token,
however, it *does* handle that much, so there is no reason to avoid that
level of complexity when it would reduce other aspects of complexity. So
a three deep stack is no real problem, especially since most FORTH words
ought to be seven or less non-stack words in length.  (*Most*, not all;
just as *most*, but not all, traditional language programs should be
seven lines or less in length.  (Actually, Constantine and Yourdon use
10 lines here, but seven seems more consistent with their other
arguments.))

I would argue, then, that the parameterized call format is only
marginally less complex than the FORTH implicit call.  During initial
coding, I certainly prefer the FORTH form; it means less work for me.
During later debugging, explicit parameter lists are often more
important.  I would suggest that the ideal programming environment (note,
*not* ``language'') would enable the programmer to enter only the
subroutine name and when necessary (that is, when FLIP FLOP PLOP would
otherwise be necessary) a shorthand form of the argument list, but
would check and, *on command*, display the complete parameter lists. I
don't know of any such environment.  (I would say FORTH with the
addition of named parameters comes close, but that is my FORTH bias
showing through again.:-)

In conclusion, I think we can now see at least one reason why FORTH
programmers defend the parameterless FORTH words so vigorously:  it
means they don't have to type so much! :-)

-- R. David Murray    (DAVID@PENNDRLS.BITNET, DAVID@PENNDRLS.UPENN.EDU)

P.S.: I do not expect you to be converted by my argument, Fraser; rather,
I understand yours more fully now.  But I think that FORTH, especially
with the modern additions to the traditional techniques, is closer to
the ideal than you give it credit for.  Certainly it is close enough
that I will not abandon its other advantages because it does not
have parameter lists.  Especially for personal projects.