tulipemoutarde.be

Software Developer

Smalltalk, Swift, Java, Obj-C

@fstephany | Email | LinkedIn

I'm currently working at Ta Mère SCRL a small development shop in Belgium.

We mainly do mobile apps (iOS, Android) for clients. We also have a strong interest in Pharo Smalltalk and Rust.

logo Ta Mère SCRL

Smalltalk for the Rubyist

09 Dec 2011 in ruby smalltalk 

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:

  • Squeak, the most famous implementation. The project has quite a long history. The development seems to have slowed down a bit 3-4 years ago but Squeakers are working hard now.
  • Pharo, a fork of Squeak. The goal of the Pharoers is to produce a clean and industry-capable Smalltalk. It all started when some people were really pissed off by the inaction of the Squeak community. Backward compatibility was a pretext for doing nothing. Pharo moves fast and does not aim to stay backward compatible with Squeak. Many projects still runs on the two without a itch though.
  • GNU Smalltalk, an alien implementation. You can use your favorite text editor with it. It is a clean implementation but it maybe misses a complete environment.
  • Amber, a smalltalk that compiles to Javascript. Pretty young but already impressive. It can be used with Node.js or in the browser.

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 ?

  • You can inspect object in live. You are working with a webservice and want to inspect the answer? Just inspect the response.
  • Change values on the fly. You wanna know what happens if that variable is -5 instead of 5? Change its value to see what happens.
  • You can actually code in the debugger. The debugger (or a stacktrace) is not an analysis tool anymore. You can actually code in it. A method is missing? Oops. Create it on the fly and continue the execution from where it failed.
  • Fast tests, all the time. Corey Haines teaches you how to get fast tests in rails. You do not need this in Smalltalk as your web/test/whatever framework are already loaded. Of course, if your tests starts to rely on external depencies (disk/network/etc) without mocking, they’ll get slow. No surprises.

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?

  • Adding methods on runtime? You are already in runtime.
  • Handle method_missing? Welcome doesNotUnderstand.

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

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.