I seem to be on a roll myth busting. This one is prompted by a comment by Peter Kriens, in response to my previous post on Java and component models. The sentences that drew my attention where "interestingly, the type information in the language allows us to provide quite a few guarantees." and "for large systems where you get legacy parts from all over the place there is something to say for type information ..."
Now it would be only fair to allow Peter to explain himself further and not to read to much into what he has said, but his words did bring to mind a common myth, namely that dynamic languages have no type information, and perform no type checking. Well they do!
I'm old enough to remember programming in C, with no stack trace and the dreaded "Segmentation fault - Core dump" Unix message on program failure. C allowed no type information at runtime. You could declare pointers of type (void *), which meant that they could point to anything you liked. You could cast to an assumed type and the language would not check for you - in the end you would try to access a segment of memory not allocated to you by the System and bang!
Here is where my memory gets a bit hazy, but I believe things improved with C++. There was still void* pointers, but I believe C++ introduced a dynamic cast that did some checking at runtime.
So a long intro, but I wanted to get everyone on to the same page. So dynamic languages like Smalltalk do their type checking at runtime. If a type mismatch is detected, the program doesn't go bang like with C, but the language notifies you of the error and will even launch a debugger at the appropriate line of code. So Smalltalk is a strongly typed language, the difference between it and say C++ is that the type checking occurs at runtime not compile time (Smalltalk also gets rid of void* pointers, Java does likewise).
So what are the consequences of these differences?
* Well with Smalltalk, all type mismatch errors can only be detected by running your programming. So no coincidence then that test driven development and SUnit came from the Smalltalk community. With C++ the compiler at compile-time performs checks statically. So some believe that unit testing is less critical (I disagree).
* With Smalltalk, the overhead of dynamic message dispatch and the runtime checks makes the language inherently slow. With C++ there are few runtime checks, all function call indirection is removed at compile time and hard coded into a VTable. This allows for the use of an optimising static compiler, which inherently produces faster runtime code.
* Smalltalk is fully polymorphic at runtime. What this means is that objects can take many forms (implementations) at runtime. So any class of object that satisfies a caller’s request can be substituted in at runtime. This is known as late-binding, and has significant implications. C++ is only partially polymorphic at compile-time, common interfaces must share a common implementation (A common base class or abstract base class). At runtime object type is fixed (hard-coded), so no polymorphism.
So along comes Java. Without justification, I will assert that Sun produced Java in a hurry. Oak was aimed at low powered, low memory home devices, so the static optimising compiler route was the obvious one to take. So Java has inherited many of the properties of C++. Namely, highly performant and static (fixed).
For Objects that come 'alive', you require different properties. Sun did a lot of research in this area. The Self Project determined that Objects needed to poses a number of properties:
* Directness (you manipulate objects directly)
* Uniformity (everything is an object)
* Liveliness (modeless, no run/edit mode, fully dynamic)
These properties are inherent in Smalltalk, and the Self Project hoped to build on them. Self explored a number of important OO concepts that are still relevant today, but the implementation was a memory hog, and you needed a super fast computer to run Self.
Here is a good video on Self.
So the reason for saying all of this is that "compile-time' type safety was always an after thought with Java. The real reason why Java is static is performance. Also from a Marketing point of view the static label was useful, as the bulk of the developer community out there were C++ programmers and comfortable with the static programming approach. To them liveliness meant nothing.
In 1995 some of the original Self team were ready to launch a new Smalltalk implementation known as Strongtalk. The idea was to address what was seen by many as the shortfalls of Smalltalk - slow performance and no compile time type checking. They addressed the performance problem by optimising out dynamic method dispatch at runtime using a dynamic compiller. The approach was similar to that used in the JVM JIT today, but their approach also allowed for de-optimisation on the fly back to interpreted code, allowing them to satisfy the semantics of dynamic dispatch needed for 'liveliness'.
They also looked at the runtime type checking issue. At first they made the same mistake as C++/Oak etc and assumed that compile-time type checking had to do with the runtime implementation. It doesn't. Type declarations in a static language can be thought of as annotations. They annotate the code and tell the compiler how best to optimise method calls. They also allow the compiler to perform checks. What the Strongtalk team did was to delegate the optimising role to a dynamic runtime and retain the static type checking at compile time. To do this they needed to add Type declarations to the Smalltalk source code, this is done by way of annotation. So Strong talk can compile both Type annotated code and un-annotated code. At runtime Strongtalk maintains full dynamic messaging semantics - so you end up with the best of both worlds.
As the startup company who built Strongtalk in secret where about to launch it on the world, Sun came along and bought them up. The Strongtalk developers where moved over to work on Java and the JVM and are responsible for the Java hotspot JIT technology we have today. Type-feedback and Type annotations sat on the shelf for over 10 years.
Fortunately Sun as recently released the Strongtalk code as Open Source:
Strongtalk Home Page
But imagine how things would have been different if they had released Strongtalk as a product in 1995? Or better still if they had ported Java to Strongtalk using Type annotations?
* There would be no OSGi (no need)
* Ruby probably would not have blossomed beyond the Perl community (no need).
* Smalltalk would perhaps still be thriving today.