TulipeMoutarde.be

About

Smalltalk for the Rubyist

Written on December 9 2011.

This blog post was written a long time ago and may not reflect my current opinion or might be technically out of date. Read with a grain of salt.

After my previous post about the Pharo ecosystem, some people asked me more about a comparison of Smalltalk and Ruby. And how a Rubyist could leverage his knowledge when learning Smalltalk.

The two languages are class based, dynamic and their supporters like their clean and easy syntax. Actually, Smalltalk is sometimes considered as one of the father of Ruby. They share quite a lot and most of the patterns used in one can be easily expressed in the other.

This post does not cover the basic syntax of Smalltalk. If you want to learn it (15 minutes max), wikipedia should be enough.

Implementations

Ruby comes in different flavors: MRI, YARV, Rubinius, JRuby, Maglev, etc. So does Smalltalk. The principal difference is that they are no “official” distribution. Every dialect has its own ecosystem and tools. Some are open source, some are proprietary.

Choosing an implementation can be a quite challenging task. If you want to go the open source way:

I’m not really interested in proprietary implementations but there are three big players in that field: Cincom Smalltalk, VA Smalltalk, Gemstone/S.

Gemstone is not only a Smalltalk implementation but also an extremly scalable object-database. Actually Maglev is a Gemstone based products. If you’re serious about Ruby, you should definitely give Maglev a look.

My favorite implementation is Pharo. I like the energy in the community and its direction. It is for me the best bet for the future. It very similar to squeak but this screenshot of the main menu is enough to convince me.

Pharo 4.2 and Pharo 1.4 world menu

You can follow this thread on stackoverflow to get the opinions of others.

The Environment

Here comes the biggest problem when learning Smalltalk. That’s where people usually get lost. Smalltalk code does not lie on a plain text file. There are literally no “code time”, it’s always runtime. It would be like coding in an IRB session. You manipulate objects all the time. Consequences ?

Actually some tools are starting to appear in Ruby. Pry is pretty damn cool Ruby tool. Once you’ll get used to Smalltalk environments you’ll want more.

When you load a library in your image, it lies next to your code. You can then read it, inspect it, put breakpoint in it and do whatever you want with it.

An image contains your code and all the libraries you want. It acts as a container and is completely independent from other images.

Metaprogramming, Object and Classes

Okay, that one is tricky. What do you expect from meta-programming?

As method_missing in Ruby, doesNotUnderstand must be used carefully. The usual advice applies in Smalltalk.

Actually defining a class in Smalltalk is just sending a message (“calling a method” in Smalltalk jargon) to the class Object. Adding a method is also a matter of sending a message to define it. The only difference is that you use tools to do it. Remember, it’s runtime and your environment is the running your code. That living environment comes with great responsibilities. If you try something along Object := nil I guess you’re a footing yourself in the foot.

If you want to learn more about the Smalltalk object system, I warmly recommend the chapter 13 of the Pharo By Example free book. If you don’t know that much about Ruby’s object system, I recommend the Dave Thomas presentation at Scotland on Rails 2009.

Returns

Methods need explicit returns (with ^). If omitted, the method will return self.

You get implicit returns for blocks: the value of the last instruction is the the value returned by the block. If you return (with ^) inside a block, it is a return value for the method.

Syntax Convention

Methods name and variables are spelled in CamelCase. Abbreviations are usually avoided. Smalltalk uses keyword based method name (as in Objective-C). Many Ruby libraries/framework mimic this by passing an hash as argument.

The tabs vs. spaces does not exist in the Smalltalk community. In every tool, press Tab to indent and you’re done.

As usual, just keep the global syntax style of the project you’re working on.

Usual suspects

Be careful when using cascades, a common is mistake is the following:

programmingLanguages := OrderedCollection new
  add: 'Ruby';
  add: 'Java';
  add: 'Haskell'

In the end of the execution, programmingLanguages will be the String Haskell. That’s because the method add: returns its argument, not self. To prevent this, send yourself at the end of the cascade:

programmingLanguages := OrderedCollection new
  add: 'Ruby';
  add: 'Java';
  add: 'Haskell';
  yourself.

Another trick of the the language is the evaluation order:

  3 + 4 * 5  #=> 35 and not 23

Evaluation is done from left to right. Mathematical order is not preserved. Indeed, + and * are simple methods. Smalltalk does not even know (and does not care) that it is executing mathematical instructions. You must use parenthesis to express precedence:

  3 + ( 4 * 5 ) #=> 23</pre></div>

Version Control

My previous post will explain you how to version Smalltalk code. Do not expect Git, Mercurial or Subversion (although they can be used as backends for Monticello).

Conclusion

Once again, this post is inspired by someone else doing the same for Javascript (thanks Greg Spurrier for the link). The Squeak by Example or Pharo By Example books are worth to read. Beware that the tools described in the book are sometimes outdated but the principles are still perfectly valid.