Generalized Object Modules Design

Lex Spoon lex at cc.gatech.edu
Wed Mar 6 18:47:55 UTC 2002


>       We could make up a term called "congruence" for some better way 
> to establish degrees of equivalence than signatures or interfaces. 
> There needs to be more semantics in congruence than the simple 
> matching that most systems do now.
> 
> What are some good ways to do this?
> 

A can of worms indeed!  But it's an important part of programming
languages, and it needs to be cracked some day or another.

Let me suggest two key ideas, and then toss them around a little:

	1. Don't have the computer check the types.

	2. Types are attached to objects, not to modules or to classes.  In
fact, let's call them "dynamic types", and let's note that classes are
dynamic types.  Thus, we are really talking about the next generation of
classes.  :)


The first issue I have taken as common sense for a while now.  Computer
type systems are increasingly baroque as they attempt to describe larger
classes of programs.  Even so, I don't think there is any type system in
common use that can handle the arithmetic operations in Squeak's
collection hierarchy: they are parametric by the number of dimensions of
nested collections!  It's not even a big loss to drop the computer
checks; consider that most code has bugs, and thus that most code isn't
even correct.  How useful is it to have a formal proof that one
incorrect module is substitutable for another module that is incorrect
in different ways?

The second issue came together as I wrote the first version of this
email, and it prompted me to rewrite it.  :)  It combines ideas from
many directions: static typing, the idea of classes being dynamic
entities, and the ideas Nathanael and others have been batting around
involving mixing classes together.  Why should an object have just one
type?

It also plays into the static vs. dynamic languages idea.  In a static
language, you spend a lot of effort reasoning about the program before
you run it.  In a dynamic language, you just put it together and fire it
up.  Dynamic languages have simple and probably more natural reasoning,
but they delay the detection of any problems.


And also, many language theorists say there is no such thing as a
"dynamic type", and procede to talk about types in a way that indeed
makes no sense with respect to this thread.  Well, of course those
theorists are simply talking about "static types".  Our dynamic types
make perfect sense once you ignore certain assumptions such as "the
compiler will prove the assertions".  :)

Okay, let's get a little more specific.

Static and dynamic guys agree that types should be named by humans. 
Even if you have the computer doing lots of checks for you, the human is
the only one who can know what types are interesting to reason about. 
The difference here is that the types won't be checked.  If the silly
human says "pi are PerfectSquare", then the computer should let it pass.

Putting types on the objects instead of the classes is not only useful,
but sometimes necessary.  The simplest example I know is: "An Array of X
is of type Comparable, if and only if X is of type Comparable".  This
typing pattern shows up a lot in Smalltalk.  To generalize, any generic
object can have functionality that is only present when its elements
have certain functionality.  In Smalltalk you implement this in the most
natural way of writing a method and supposing that the elements meet
whatever precondition you need; in statically typed languages you either
don't write them or you write your program in a way that will have lots
of dynamic type checks.

Many times objects can almost but not quite talk directly to one
another.  Suppose we allow humans to write intermediary objects that
negotiate between such objects?  In particular, successive versions of a
module will often have such types:  A 2.8 Morph can *almost* talk to a
3.2 morphic world.  If types have versions, then this provides a hook
for programmers to add intermediaries.

Alternatively, we can write conversion routines instead of
intermediaries, I suppose, the way SmartRefStream does.  Conversion
routines have the advantage that they don't cause a recursive problem of
what to do with out-of-date intermediary objects.  :)

Finally, since this is Smalltalk, the types would surely be objects. 
There are a lot of nice things you can hang from the type objects.  For
one, the intermediary-creation routines can be placed there.  For
another, you can put a dynamic type check there; if someone asserts "x
is of type Foo", then the Foo object could actually analyze i.

Probably, types should stick to objects once they are asserted on them,
at least by default.  If you an assert a type on the same object twice,
then the check is only done one time.  Unfortunately, types must also
sometimes be removed -- suppose you assert Comparable on an array of
numbers, and then stick a morph in the array.  The stickiness supports
some nice program-understanding tools, incidentally -- when you open an
inspector, you see not only the class of the object, but all dynamic
types that have been asserted on it.


Phew.  It's a lot of fun thinking of types actually doing something
useful.  I always picture a static type system as a stern-faced English
professor with ruler in hand, taking off 10 points for each misspelled
word.  Static type systems filter out programs that might otherwise work
fine together.  These dynamic type systems, to contrast, could grease
the communication between different image segments that wouldn't have
been able to talk before....


-Lex



More information about the Squeak-dev mailing list