[net.micro] Smalltalk, CLU, and 432

txr.usc-cse@Udel-Relay (12/28/82)

(In response to the message of Mike Meyer, and the message of Robert
Scheifler.)

When I first read the message from Mike Meyer, I thought it a simple
case of misunderstanding, helped along on my part by providing a
misleading statement.  Upon re-reading my original letter, however, I
have a different view.  If I may quote from Mike's letter:

    "I've even written object oriented code in FORTRAN..." BINGO! That
    statement reveals that the object/message paradigm isn't a property of
    a language, but a veiwpoint one uses for solving problems. As such, any
    solution using said pardigm can be used in any language. The thing that
    makes smalltalk different from `conventional' languages is that it
    directly supports the object/message pardigm, whereas other languages
    don't.

Now there is a paragraph that is exemplary in striving for
misunderstanding.  Starting off with a misquote, and out of context as
well, it goes on to a sweeping generalization.  Here is the original,
actual quote:

    I hope I won't be accused of heresy if I confess that I have done
    object oriented programming in (horrors) FORTRAN.  But (!) it was
    arduous, and the language was strained, and furthermore there are some
    ST mechanisms that just don't carry over -- if I wanted them in FORTRAN
    I'd just have to give up.  (The same goes for Ada and the rest.)

Pause here a moment and ask yourself a few questions.  Is is possible
to do (1) structured programming in assembly language, (2) recursive
programming in FORTRAN, (3) object oriented programming in Mesa ?  The
answer to all of these questions is a qualified "yes."  Case (2)
provides the clearest example:  by playing games with saving state
explicitly, allocating "local variables" explicitly, and so forth, it
is indeed possible to write in FORTRAN code that models a standard
recursive program.  But FORTRAN is NOT a recursive language, period.

In the same way, just because it is possible to transform some object
oriented programs into FORTRAN, does not mean that FORTRAN is an object
oriented language.  Nor does it mean that OOP is a "viewpoint one uses
for solving problems."  (Would you call recursion a "viewpoint"?)

Before we get capsized in a sea of emotional issues, let us turn to the
issues and examples provided by the CLU people.  While it is true that
you can parameterize a cluster w.r.t. a type, and thereby use the same
code for many different types of "elements," (as in the tree example),
you still have to instantiate the cluster for the particular type you
are interested in, i.e., Tree[ Int ].  This may seem like trivial
overhead, but it is overhead, at least when compared to the Smalltalk
case.  In CLU there must be Tree[ Int ], Tree[ Real ], ..., for each
data type that you want a tree of.  In Smalltalk there is only Tree.
[Note:  please don't get the mistaken impression that this is, in any
way, an attack on CLU.  It isn't.]

Another difference between CLU and Smalltalk is whether the leaves of
the tree can have mixed types.  In Smalltalk, a given tree could have
in its leaves a mixture of (say) integers and blocks (which when
evaluated produced an appropriate arithmetic type, an integer or even a
real).  In CLU, it is either Tree[ Int ], Tree[ Block ], or Tree[ Real ],
not a mixture of the three -- the leaf types must all be the same.

Furthermore, if something accepts a tree as an argument, it must be
paramterized w.r.t. the type of the tree.  One can imagine a register
counting algorithm, accepting a tree as input, that must now be
parameterized w .r.t. the type of the tree, even though the algorithm
changes not at all for different tree types.  CLU, which is supposed to
be hiding details through its abstraction mechanism, cannot quite hide
all the details -- the fact of parameterization must be made available
outside the cluster.

(Along the same lines, imagine the register counting algorithm expanded
to allow DAGs as input.  Now the level of parameterization is two deep,
i.e., we will have RCA[ DAG[Int] ], RCA[ DAG[Real], RCA[ Tree[Int] ],
RCA[ Tree[Real] ].  There is some kind of non-linear code growth going
on here.  Note that RCA almost certainly doen't depend on whether the
leaves are Ints or Reals -- in fact, if things work out, it may not
even distinguish between DAGs and Trees (provided we take the care to
insure DAGs and Trees respond to the same operators).  In Smalltalk
there is only RCA.)

On the subject of code growth, it is easy to believe that paramterized
clusters could generate non-linear code growth.  The CLU manual states
that paramterization is best understood in terms of a replacement rule.
If such replacement is carried out at the textual level, it would
result in a copy of a cluster for each of the types with which it is
instantiated, which is non-linear code growth.  CLU doesn't actually do
the parameterization by replacement, but the lack of polymorphism
should result in non-linear code growth somewhere.

It is true that, since in effect CLU has procedure variables, you can't
always tell at compile time which procedure will be called (and I
express thanks to Robert Scheifler for correcting me on this).  If,
however, you don't use procedure variables but just use the normal
cluster mechanism, you always can tell at compile time which procedure
will be called.  Even if you do use procedure variables, you can still
tell at compile which procedure variable will be accessed.  In this
view of the world a cluster (instantiation) is a record of operations,
with the Type$operation notation extracting a field out of the
operation record .  Compare this with Smalltalk, which does not require
you to store "procedures" into "procedure variables," yet still has the
property of the same message invoking different methods.  (Note that,
at a given moment in time, a CLU procedure invocation will refer to
exactly one procedure, whereas in Smalltalk a message may refer to any
one of a number of messages, depending on the receiver of the message.)

All of the preceding ignores the benefits of a good inheritance
mechanism, which Smalltalk has, and which CLU does not.  A good
inheritance mechanism allows for factoring, the property of one thing
being in one place.  Factoring makes linear code growth possible, but
it also allows a lot more, such as synchronicity, modifiability, and
differential programming ("something just like X, except...").

[Let me say again that I am not trying to diminish CLU.  I am, in fact,
impressed by the CLU effort, and the CLU language manual remains a
shining example (which others would do well to copy) of lucid brevity.]

If you're looking for "features" that Smalltalk has, but other
languages don't, inheritance is a good place to start.  (I know that
some LISPs have an inheritance mechanism in the form of FLAVORS, wasn't
that just taken from Smalltalk?)  The other interesting thing about
Smalltalk is that it accomplishes so much with so little.  The language
is incredibly tiny, especially when compared to monstrosities like ADA.

Turning back to the iAPX432, or to machine architectures in general if
you will, why isn't the 432 object oriented?  What could be done to
make it object oriented?

The philosphy behind 432 objects is different from ST objects.  432
objects are BIG, and have lots of overhead (like hundred of bytes).  ST
objects are small, and have little overhead (less than ten bytes).  So
the architecture people should think about reducing the object overhead.

Secondly, objects should be unified, all the way down to things like
integers and reals.  The 432 has a "data object" whose purpose it is to
store Ints and so on, with compiled in add operators, etc.  Nonsense!
ST integers are objects just as windows and contexts are objects, with
messages being sent to do processing.  A far cry from the compiled add
operators on the 432.

Lastly, the 432 procedure call mechanism doesn't match the ST (aka
object oriented) message passing mechanism.  The binding time is fixed
too early on the 432.  And that's to say nothing of inheritance.  The
binding of a message must happen as determined by the receiver;  it
must happen keeping in mind the inheritance mechanisms;  and it must
not require global knowledge in order to do the binding.

(To add flavor:  the paper I wrote earlier this year (Object Oriented
Programming, September SIGPLAN) was sparked by a discussion I had about
the 432 and why it would make a lousy Smalltalk engine.  I have the
feeling I'm mostly repeating the arguments I gave in the paper.
Anybody out there actually read it?)

Tim Rentsch