Smalltalk = strongly typed?

Andreas Raab andreas.raab at gmx.de
Thu Oct 14 07:09:06 UTC 2004


Hi Blake,

> Dynamic, I get. Typed, I get. But strongly typed? Am I mistaken in 
> thinking there isn't really any type-checking at all?

Weak vs. strong typing is not primarily about type-*checking* but rather 
about whether an object (reference) uniquely belongs to a type or not. To 
give an example, in C[++] (which is statically but weakly typed) I can do 
things like:

    ((Foo*)0)->size()

e.g., take an integer, "cast it" into a Foo* and invoke methods on it. The 
weird thing is that those methods (as long as they aren't virtual) may even 
work! In Smalltalk there is no such thing, you cannot trick anyone into 
interpreting a SmallInteger object as being of type Foo. It just won't work. 
That said...

> As long as an object can accept the right messages, it will work,
> regardless of the context.

... your interpretation is entirely correct - if a Foo understands the set 
of messages that a SmallInteger understands it will work interchangeably 
with SmallIntegers. But while that may be true it still remains a Foo!

> That is, if I had a routine with two parameters, "a" and "b", and it 
> expects both to be an integer:
>
> c := a plus: b
>
> If a and b happen to be strings, this code will still work. Or if they're 
> ingredients to a recipe or...whatever, as long as they have a "plus" 
> method.
>
> Is this true? Anyone have opinions on this? I mean, I guess it's just a 
> label in the long run, but--well, I work a lot with Pascal so strong, 
> static-typing, compile-time checking is the norm for me.

You are precisely right, except the "it's just a label" part. For the 
advocates of static type checking the ability to coerce between types is 
both a blessing and a curse. It's a blessing because without the ability 
highly generic data types (like lists) are almost impossible to implement 
yet, at the same time, it completely destroys the illusion that static type 
checking would make your program "type-safe" in any meaningful way[*1]. In 
other words, how can you possibly tell whether:

    Foo *myFoo = (Foo*)list.getNext();

will answer a valid Foo or not? Even worse, how can you say whether the 
coercion operation is even valid (e.g., "understood") by the element you are 
retrieving from the list? Note that the meta-point here lies in 
acknowledging that only the object (receiver) can really decide which 
messages it (pretends to) understand. As such any "external assumption" 
about the object is prone to fail and gives raise to all of the "niceties" 
of the modern computer world, including buffer overruns (hey, the compiler 
said it'd be okay!) etc.

[*1] Or at least I haven't seen any such meaningful interpretation. It is 
true (and I won't deny it) that static types help you avoid a few mistakes 
by sending objects messages that they don't understand but in reality[*2], 
if that happens it means you haven't tested your code. But then at least you 
know what you're up against contrary to the situation where you have a foo 
cast into a Bar and wonder how it could have possibly gotten into that 
state. I have debugged programs where this has happened and I take a few 
DNUs every day single over that (in particular considering that I can fix 
them right in the debugger ;-)

[*2] The ONE good reason for static types is auto-completion btw. This 
really sucks without adequate type-information but I'm still thinking that a 
decent type-inferencer could do a perfectly good job here.

Cheers,
  - Andreas




More information about the Squeak-dev mailing list