Animorphic ST (Strongtalk) released!

David Griswold David.Griswold at acm.org
Thu Jul 25 08:46:55 UTC 2002


Hi Stefan and Andreas,

Sorry for the late reply- I've been offline for the last few days.

Several people including Andreas Raab and Stefan Aust were discussing the odd signature for the #-> message in the Strongtalk
system.  I'll explain the situation in a fair amount of detail for those who are interested, since this sort of example illuminates
the kind of interesting issues involved in typing the Smalltalk libraries.

The Strongtalk libraries have the -> signature as:

    -> other <Y def> ^<VarAssoc[X,Y]>
	    {where X is receiverType}

Andreas thought this was difficult to understand.  In fact, if you know the type system, it is quite easy to understand; it means
what it almost literally says; X is the type of the receiver known at the send site.  What *is* difficult is to understand why it is
that way and not some other way.  Stefan asked why it could not have been written using the Self type, which we could do like this,
without an inference clause:

    -> other <Y def> ^<VarAssoc[Self,Y]>

The reason I didn't use that signature is that it would not be typesafe, because you can only use Self in 'covariant' positions in
type signatures (crudely, places that return Self, not take it as an argument), if you want subtyping to work.  The issue is subtle,
and other type systems get around this sort of thing by just not having a Self type or generics, the combination of which requires
you to understand this issue, which affects *any* type system that has subtyping.  The issue is that VarAssoc is the protocol for
*mutable* associations (vs. Assoc, which is the read-only protocol), which means that Self would be the argument type for the #key:
message.  If we allowed that, we could easily violate typesafety by passing it somewhere that a weaker type for Self was know (since
Self automatically becomes more specific or general as necessary via inheritance), and then storing an invalid value into the key of
the association.  That is tricky to think about, but that is exactly what a type system does for you- it will tell you if it isn't
safe, even if it's too complicated for you to think about.

Now, this whole issue can be avoided if you just write:

    -> other <Y def> ^<Assoc[Self,Y]>

which is perfectly typesafe, easy to read and understand, and valid in Strongtalk.  Note the difference: this time I used Assoc, the
read-only protocol, instead of VarAssoc, which includes the mutation operations.  Since the association that is returned is
read-only, it becomes safe to do this.

Why didn't I use this simpler, more readable way of writing the message?  I could have, but here was my reasoning:   in code that is
not heavily reused, these subtleties don't matter much, and that signature would be fine.  But the messages in Object are used all
over the place, and so a slightly more complicated signature that is more flexible seemed preferable.  #-> is used to allocate
associations, and the caller may well want to mutate that association after it was created.

In any other type system, this would leave you stuck- you wouldn't be able to write the signature safely and still use the VarAssoc
protocol. But there is a way to do it in Strongtalk, and I used it.  Using an inference clause to 'infer' the receiver type, instead
of using Self, is a standard, easy way to get around the limitations on use of Self.  You will see it used in various places
throughout the Strongtalk libraries:

    -> other <Y def> ^<VarAssoc[X,Y]>
	    {where X is receiverType}

Whenever you see something like this, just think this: an inferred receiverType is just like Self, *except* that it is effectively
frozen (as the type known for the receiver at the call site, which is all the caller cares about, after all).  Because it is frozen,
all the tricky issues about where you can put Self just go away!  Thus, we have found a way of writing a *flexible* piece of code
(you can mutate the returned association), at the cost of this standard typing trick.  This kind of thing quickly becomes easy if
you use the type system all the time.

Now, most users don't care about this kind of thing- they just want to understand the signature.  You folks are reading this without
the benefit of any experience using the type system, and without any documentation, which is a big handicap.  I would claim that
with just a tiny bit more experience, the signature is very easy to understand- the hard thing is understanding *why* it is that
way.  And only the person writing it really needs to think about that- the user can just use it, and the type system will give him
the flexibility that the writer of the signature designed into it.  If you are writing code and you don't want to think about this
sort of thing, that's fine- you'll just have slightly less flexible code.

It's much easier to write a type system that doesn't have these kind of issues, but the cost becomes a much more rigid type system
(that in this example wouldn't let you mutate the returned association).  This is an example of the kind of flexibility that we went
to great pains to build into Strongtalk.  It also illustrates how much thought went into the library design.

Lest you think that this is a insignificant issue, a similar kind of design is essential for making it possible to type extremely
difficult things like coercive arithmetic in the numeric hierarchy.  Once again, you can just use it: it will act like you expect it
to, even if you don't understand why it is that way.

Regards,
-Dave

> From: Stefan Matthias Aust <sma at 4plus4.de>
> Subject: Re: Animorphic ST (Strongtalk) released!
> Date: Sat, 20 Jul 2002 19:49:06 +0200
>
> Andreas Raab wrote:
>
> > I found the type-system the most unnatural part about StrongTalk.
>
> For me, Strongtalk *is* the typesystem.  It's nice, if the Animorphic ST
> release is also fast, but IMHO the static type system is the more
> interesting  part.
>
>  > It
> > feels displaced and if you look at methods like "->" in Object you can
> > see that there are some rather nasty complexities associated with it
> > (not to mention readability issues).
>
> One can always argue about syntax.  That's something you have to get
> used to.  All it says is that an Association's type is created from the
> receiver and the parameter type.  I don't understand why that isn't
> written as
>
>   -> other <Y def> ^<Association[Self, Y]>
>
> Instead of <Y def>, I might prefer 'Y.  I once saw a Smalltalk dialect
> which used {} instead of <> to declare types.  That could be more readable.
>
> However, types don't become easier just by not writing them down...  You
> have to understand them to program.
>
> >>In Smalltalk (without types) no tool can exactly know the type of an
> >>expression and code completion (with is IMHO the best
> >>productivity tool of a modern IDE) cannot offer a valid
> >>selection of applicable method names.
> >
> > That has been said many times and yet, I disagree. To the best of my
> > knowledge nobody has ever tried to build a simple type inference system
>
> Perhaps, because it wont't work?
>
> > which just goes along with you as you are writing code and tries to
> > discover what the types might be.
>
> Just a little bit of type inferrence doesn't work.  Once, I tried it and
> also had some discussions with somebody who thought about writing is
> master thesis about this topic and we finally agreed upon that you'd
> need either a full features type system or stay with no types at all.
>
>  > Name completion and other utilities
> > can even be used to tell such a type inference system about what types
> > of certain objects are and I still think that you should be able to
> > trivially figure out  the types for 90% of the system
>
>   someMethod: param
>     param .
>
> Okay, please tell me the methods applicable at the "." ?  That's
> impossile if you don't want to show *all* method names of the system -
> which are probably 8000-10000.
>
> Code completion is IMHO the most important and best way to learn a class
> library.  VBA is a good example.  Using the simple built-in IDE of MS
> Word, I can script the whole program without much problems, just by some
> guessing and the code completion.
>
> > I would hope that some better syntax can be found than
> > is currently in both StrongTalk and SmallScript.
>
> Here, I agree.
>
> > But of course you do realize that *optional* types
>
> Sure, but it wouldn't be Smalltalk if you couldn't simply make the
> optional mandatory and set the requirement of type in your project.
>
> In addition, I could document my assumption by annotation types which
> would be then checked by the system and eventually get a better
> documented, well formed program.
>
>
> bye
> --
> Stefan Matthias Aust   //
> www.3plus4software.de // Inter Deum Et Diabolum Semper Musica Est
>
>
>





More information about the Squeak-dev mailing list