Understanding Smalltalk message syntax

TL;DR

This tutorial explains the syntax and evaluation order of unary, binary and keyword messages in Pharo.

What is a “message”?

Smalltalk draws a clear distinction between “methods” and “messages”. In Smalltalk “everything happens by sending messages.” In the words of Dan Ingalls, “we have a universe of well-behaved objects that courteously ask each other to carry out their various desires.” (In “Design Principles Behind Smalltalk”, Byte Magazine, August 1981. See Smalltalk history)

An object “sends a message” to another object, asking it for a service; if the receiver “understands the message”, then it has a “method” for fulling the request. The method is the request, and the method is the code to fulfil the request.

Unary messages

There are unary , binary and keyword messages in Smalltalk. A unary message consists of a word sent to a receiver object. Here, the message squared is sent to the receiver, the number 2.

2 squared
  

We can see that 2 understands the message squared because GT shows us a little grey triangle next to the message. If you click on it, it will expand to show the method for fulfilling the reuest.

Aside. Smalltalk convention is to refer to messages as literals, so we refer to this message as #squared (and not squared). This literal can be looked up in the method dictionary of the relevant class as follows:

Number>>#squared squared "Answer the receiver multiplied by itself." ^self * self

Everything is an object in Smalltalk, even classes, so you can send messages to classes too, for example:

Float pi
  

or

Date today
  

Binary messages

A binary message is an operator built up from non-alphanumeric characters, such as +, -, ,, >, <, =, and so on.

A binary message expression always consists of a receiver , the binary operator , and an argument . For example, here the receiver is the number 3, and the binary message is + 4, consisting of the operator + and the argument 4:

3 + 4
  

Note that here too, 3 understands the message #+, and has a (primitive) method to fulfil the request.

All binary operators in Smalltalk are just binary messages, since everything happens by sending messages . Some common examples:

true & false
  
3 < 4
  
'meer' , 'kat'
  

NB: := is not a message, but the built-in assignment operator.

x := 0
  

This assigns the value 0 to x, but is not a message send.

Keyword messages

Keyword messages consist of a sequence of keywords, each terminated by a colon (:), and followed by an argument. Here, for example, the keyword message raisedTo: 5 consists of the keyword #raisedTo: and the argument 5, and is sent to the receiver 2:

2 raisedTo: 5
  

To handle more arguments, simply add more keywords:

42 between: 41 and: 43
  

Here the message #between:and: is sent to the receiver 42, with arguments 41 and 43. In a language like Java, this might written:

new Integer(42).betweenAnd(41,43)

Precedence

In complex expressions, first unary messages are evaluated, from left to right, then binary, and finally keyword messages.

For example, the following expression:

2 raisedTo: 3 + 2 squared
  

is equivalent to:

2 raisedTo: (3 + (2 squared))
  

Parentheses can be used to change the precedence. Note that the following expression yields 10 and not 7:

3 + 2 * 2
  

This is easily fixed as follows:

3 + (2 * 2)
  

Cascades

An unusual feature of Smalltalk is that of cascaded messages . You can send multiple messages to the same object, by joining them with semi-colons. This is often used to build up a complex object using a sequence of messages:

myColors := OrderedCollection new
				add: #red;
				add: #green;
				add: #blue;
				yourself
  

Here we first create a new OrderedCollection, and then send four messages to this object. Note that sence the add: method returns its argument rather than the receiver, to ensure that the final result is the collection and not the literal #blue, we send a final message #yourself, which returns the collection. (This is a common idiom in Smalltalk cascades.)

Exercise

What result do you expect when evaluating the following expression?

3 factorial raisedTo: 2 squared; squared
  

Can you explain the result?

Further reading

For a short video, see Smalltalk Syntax in 7'.