Mind the dot

I never would have thought that I'll have to program in Smalltalk one day. I know Java and PHP quite well and compared to them Smalltalk -- or specifically Squeak in my case -- is awesome and very weird at the same time.

Logo if SqueakOkay, I just have to write a little wrapper layer, still I have to deal with sockets programming, implementing a Singleton, and a bit exception handling. Pretty basic if you're an experienced Smalltalk programmer, but quite a challenge if you're not.

I've learned some interesting things about the language and its development environment and I thought I share it with you. This isn't a complete Smalltalk roundup, just some notes. Feel free to add stuff in the comments and check out www.squeak.org.

Squeak and Smalltalk is definitely worth a look, it's actually an easy but powerful first-contact programming language, so don't be frightened by my technical gibberish below.

Let's start with some language basics.

In contrast to Java or most other imperative programming languages Smalltalk consists of very few atoms. In fact there isn't even an if or while statement. Instead it's all about sending messages to objects and in Smalltalk literally everything is an object -- including booleans and integers.
So if you want to execute a piece of code when a boolean condition is met (aka. if), you send an ifTrue message to condition, which is an object of type Boolean, and add the code as a parameter.

condition ifTrue: [ doSomething. ].

Iterating through a for-loop is basically the same: Send a do: event to an interval object.

(1 to: 10) do: [:n | result := result + n ].

Notice that the interval object is implicitly created by sending the message to: 10 to the object 1.

The funny thing is that the language is highly dynamic. Not only in the sense that the actual type of an object and the method called is determined at runtime (so vehicle.forward() will work for Vehicle vehicle = new Car() and Vehicle vehicle = new Bike(), although they have different implementations for .forward()), but also in the sense that existing classes and objects can be modified at runtime. Even if they belong to the core system.

To do this, you can browse all existing classes and its methods in the "System Browser". A sophisticated inspection tool, that lets you not only browse all classes currently available, but you can also edit them right in place. That includes system classes, so if you don't like how the "System Browser" -- which is itself an object -- works, you can easily create a subclass or you just modify the existing one.

It's really convenient that Squeak -- an open source implementation of the Smalltalk-80 language -- comes with everything you might need. A nifty GUI toolkit called "Morphic", powerful frameworks and toolkits for doing all kinds of stuff from string manipulation to web services, and a mighty "System Browser" which serves as a development environment for your programs and offers you access to the source code of almost any part of the system, the toolkits, etc.


Of course Squeak/Smalltalk also has some downsides. Some of them are just a question of habituation and others may be fixed by using the right tools (which I don't know yet :).

First of all, it takes some time until you get used to its syntax, especially if you're used to another language like Java. In Java multiple commands are separated by ";", Smalltalk uses ".". In the first few days you'll probably quite often confuse the first with the latter, like I do now. Until you've mastered spotting syntax errors in a fraction of a second these typos will be really time consuming.

What really sucks is syntax checking in the "System Browser", which is automatically performed when you save your work or when you want to take a look at different classes or methods.
Till now I don't find the error messages generated by Squeak particularly useful. "Unknown selector" was the error message that encouraged me today to spend some hours fixing a super tiny syntax error. I just missed the point "." at the end of the code block below (I found tons of examples without the dot on the internet. They work fine if and only if this block is the last one in your method).

Finally, lets take a look at the piece of code that took my some hours fix and en passant let us checkout how exception handling is done.

  "this is a comment"
  | a b c |   " declare temporary variables"
  a := 15.
  b := 0.
  c := a /b.
  Transcript show: 'No exception.'.  " Transcript is a global log window you can open " 
   on: Exception, Error, ZeroDivide
        [:exception |
            Transcript show: 'Exception!'; cr.] .  "

Read carefully! Isn't that awesome? Exception handling is done by sending the appropriate messages on: and do: to a BlockContext object (which is generated from the code inside the squared brackets). Don't like how this is implemented? Need to log every exception in the system? Fire up your System Browser and modify that class at runtime. That just rocks.

Check it out: www.squeak.org

Update: If you know Squeak's basics you may find this cheatsheet useful.

There is 1 Comment