Chapter 4
Understanding message syntax

Although Smalltalk’s message syntax is extremely simple, it is unconventional and can take some time getting used to. This chapter offers some guidance to help you get acclimatized to this special syntax for sending messages. If you already feel comfortable with the syntax, you may choose to skip this chapter, or come back to it later.

4.1 Identifying messages

In Smalltalk, except for the syntactic elements listed in Chapter 3 (:=  . ; # () {} [ : | ]), everything is a message send. As in C++, you can define operators like + for your own classes, but all operators have the same precedence. Moreover, you cannot change the arity of a method. “-” is always a binary message; there is no way to have a unary “-” with a different overloading.

In Smalltalk the order in which messages are sent is determined by the kind of message. There are just three kinds of messages: unary, binary, and keyword messages. Unary messages are always sent first, then binary messages and finally keyword ones. As in most languages, parentheses can be used to change the order of evaluation. These rules make Smalltalk code as easy to read as possible. And most of the time you do not have to think about the rules.

As most computation in Smalltalk is done by message passing, correctly identifying messages is crucial. The following terminology will help us:


PIC

Figure 4.1: Two messages composed of a receiver, a method selector, and a set of arguments.

PIC

Figure 4.2: aMorph color: Color yellow is composed of two message sends: Color yellow and aMorph color: Color yellow.


A message is always sent to a receiver, which can be a single literal, a block or a variable or the result of evaluating another message.

To help you identify the receiver of a message, we will underline it for you. We will also surround each message send with an ellipse and number message sends starting from the first one that will be sent to help you see the order in which messages are sent.

Figure 4.2 represents two message sends, Color yellow and aMorph color: Color yellow, hence there are two ellipses. The message send Color yellow is executed first so its ellipse is numbered 1. There are two receivers: aMorph which receives the message color: ... and Color which receives the message yellow. Both receivers are underlined.

A receiver can be the first element of a message, such as 100 in the message send 100 + 200 or Color in the message send Color yellow. However, a receiver can also be the result of other messages. For example in the message Pen new go: 100, the receiver of the message go: 100 is the object returned by the message send Pen new. In all the cases, a message is sent to an object called the receiver which may be the result of another message send.


Message send Message type

Result

Color yellow unary

Creates a color.

aPen go: 100. keyword

The receiving pen moves forward 100 pixels.

100 + 20 binary

The number 100 receives the message + with the number 20.

Browser open unary

Opens a new browser.

Pen new go: 100 unary and keyword

A pen is created and moved 100 pixels.

aPen go: 100 + 20 keyword and binary

The receiving pen moves forward 120 pixels.


Table 4.1: Examples of Message Sends and their Types

Table 4.1 shows several examples of message sends. You should note that not all message sends have arguments. Unary messages like open do not have arguments. Single keyword and binary messages like go: 100 and + 20 each have one argument. There are also simple messages and composed ones. Color yellow and 100 + 20 are simple: a message is sent to an object, while the message send aPen go: 100 + 20 is composed of two messages: + 20 is sent to 100 and go: is sent to aPen with the argument being the result of the first message. A receiver can be an expression (such as an assignment, a message send or a literal) which returns an object. In Pen new go: 100, the message go: 100 is sent to the object that results from the execution of the message send Pen new.

4.2 Three kinds of messages

Smalltalk defines a few simple rules to determine the order in which the messages are sent. These rules are based on the distinction between 3 different kinds of messages:

Unary messages

Unary messages are messages that do not require any argument. They follow the syntactic template: receiver messageName. The selector is simply made up of a succession of characters not containing : (e.g., factorial, open, class).

 
89 sin           -→ 0.860069405812453 
3 sqrt           -→ 1.732050807568877 
Float pi         -→ 3.141592653589793 
blop size     -→ 4 
true not        -→ false 
Object class -→ Object class  "The class of Object is Object class (!)"  

Unary messages are messages that do not require any argument.
They follow the syntactic template: receiver selector

Binary messages

Binary messages are messages that require exactly one argument and whose selector consists of a sequence of one or more characters from the set: +, -, *, /, &, =, >, |, <, ~, and @. Note that -- is not allowed for parsing reasons.

 
100@100      -→ 100@100  "creates a Point object" 
3 + 4              -→ 7 
10 - 1            -→ 9 
4 <= 3            -→ false 
(4/3) * 3 = 4   -→ true  "equality is just a binary message, and Fractions are exact" 
(3/4) == (3/4) -→ false  "two equal Fractions are not the same object"  

Binary messages are messages that require exactly one argument and whose selector is composed of a sequence of characters from: +, -, *, /, &, =, >, |, <, ~, and @. -- is not possible.
They follow the syntactic template: receiver selector argument

Keyword messages

Keyword messages are messages that require one or more arguments and whose selector consists of one or more keywords each ending in :. Keyword messages follow the syntactic template: receiver selectorWordOne: argumentOne wordTwo: argumentTwo

Each keyword takes an argument. Hence r:g:b: is a method with three arguments, playFileNamed: and at: are methods with one argument, and at:put: is a method with two arguments. To create an instance of the class Color one can use the method r:g:b: as in Color r: 1 g: 0 b: 0, which creates the color red. Note that the colons are part of the selector.

In Java or C++, the Smalltalk method invocation Color r: 1 g: 0 b: 0 would be written Color.rgb(1,0,0).
 
1 to: 10                        -→ (1 to: 10)  "creates an interval" 
Color r: 1 g: 0 b: 0       -→ Color red  "creates a new color" 
12 between: 8 and: 15 -→ true 
 
nums := Array newFrom: (1 to: 5). 
nums at: 1 put: 6. 
nums -→ #(6 2 3 4 5)  

Keyword based messages are messages that require one or more arguments. Their selector consists of one or more keywords each ending in a colon (:). They follow the syntactic template:
receiver selectorWordOne: argumentOne wordTwo: argumentTwo

4.3 Message composition

The three kinds of messages each have different precedence, which allows them to be composed in an elegant way.

1.
Unary messages are always sent first, then binary messages and finally keyword messages.
2.
Messages in parentheses are sent prior to any kind of messages.
3.
Messages of the same kind are evaluated from left to right.

These rules lead to a very natural reading order. Now if you want to be sure that your messages are sent in the order that you want you can always put more parentheses as shown in Figure 4.3. In this figure, the message yellow is an unary message and the message color: a keyword message, therefore the message send Color yellow is sent first. However as message sends in parentheses are sent first, putting (unnecessary) parentheses around Color yellow just emphasizes that it will be sent first. The rest of the section illustrates each of these points.


PIC

Figure 4.3: Unary messages are sent first so Color yellow is sent. This returns a color object which is passed as argument of the message aPen color:.


Unary > Binary > Keywords

Unary messages are sent first, then binary messages, and finally keyword messages. We also say that unary messages have a higher priority over the other kinds of messages.

Rule One. Unary messages are sent first, then binary messages, and finally keyword based messages.

Unary > Binary > Keyword

As these examples show, Smalltalk’s syntax rules generally ensure that message sends can be read in a natural way:

 
1000 factorial / 999 factorial -→ 1000 
2 raisedTo: 1 + 3 factorial     -→ 128  

Unfortunately the rules are a bit too simplistic for arithmetic message sends, so you need to introduce parentheses whenever you want to impose a priority over binary operators:

 
1 + 2 * 3   -→ 9 
1 + (2 * 3) -→ 7  

The following example, which is a bit more complex (!), offers a nice illustration that even complicated Smalltalk expressions can be read in a natural way:

 
[:aClass | aClass methodDict keys select: [:aMethod | (aClass>>aMethod) isAbstract ]] value: Boolean -→ an IdentitySet(#or: #| #and: #& #ifTrue: #ifTrue:ifFalse: #ifFalse: #not #ifFalse:ifTrue:)  

Here we want to know which methods of the Boolean class are abstract1 . We ask some argument class, aClass, for the keys of its method dictionary, and select those methods of that class that are abstract. Then we bind the argument aClass to the concrete value Boolean. We need parentheses only to send the binary message >>, which selects a method from a class, before sending the unary message

isAbstract to that method. The result shows us which methods must be implemented by Boolean’s concrete subclasses True and False. Example. In the message aPen color: Color yellow, there is one unary message yellow sent to the class Color and a keyword message color: sent to aPen. Unary messages are sent first so the message send Color yellow is sent (1). This returns a color object which is passed as argument of the message aPen color: aColor (2) as shown in example 4.1. Figure 4.3 shows graphically how messages are sent.

Example 4.1: Decomposing the evaluation of aPen color: Color yellow
 
        aPen color: Color yellow 
(1)                       Color yellow        "unary message is sent first" 
                        -→ aColor 
(2)   aPen color: aColor                 "keyword message is sent next"  
Example. In the message aPen go: 100 + 20, there is a binary message + 20 and a keyword message go:. Binary messages are sent prior to keyword messages so 100 + 20 is sent first (1): the message + 20 is sent to the object 100 and returns the number 120. Then the message aPen go: 120 is sent with 120 as argument (2). Example 4.2 shows how the message send is executed.
Example 4.2: Decomposing aPen go: 100 + 20
 
      aPen go: 100 + 20 
(1)                 100 + 20           "binary message first" 
                   -→   120 
(2)  aPen go: 120                   "then keyword message"  

PIC

Figure 4.4: Binary messages are sent before keyword messages.

PIC

Figure 4.5: Decomposing Pen new go: 100 + 20

Example. As an exercise we let you decompose the evaluation of the message Pen new go: 100 + 20 which is composed of one unary, one keyword and one binary message (see Figure 4.5).

Parentheses first

Rule Two. Parenthesised messages are sent prior to other messages.

(Msg) > Unary > Binary > Keyword

 
1.5 tan rounded asString = (((1.5 tan) rounded) asString) -→ true    "parentheses not needed here" 
3 + 4 factorial   -→ 27    "(not 5040)" 
(3 + 4) factorial -→ 5040  

Here we need the parentheses to force sending lowMajorScaleOn: before play.

 
(FMSound lowMajorScaleOn: FMSound clarinet) play 
"(1) send the message clarinet to the FMSound class to create a clarinet sound. 
 (2) send this sound to FMSound as argument to the lowMajorScaleOn: keyword message. 
 (3) play the resulting sound."
 
Example. The message (65@325 extent: 134@100) center returns the center of a rectangle whose top left point is (65,325) and whose size is 134×100. Example 4.3 shows how the message is decomposed and sent. First the message between parentheses is sent: it contains two binary messages 65@325 and 134@100 that are sent first and return points, and a keyword message extent: which is then sent and returns a rectangle. Finally the unary message center is sent to the rectangle and a point is returned. Evaluating the message without parentheses would lead to an error because the object 100 does not understand the message center.
Example 4.3: Example of Parentheses.
 
      (65@325 extent: 134@100) center 
(1)   65@325                                                    "binary" 
    -→ aPoint 
(2)                                134@100                     "binary" 
                                 -→ anotherPoint 
(3)   aPoint extent: anotherPoint                       "keyword" 
      -→ aRectangle 
(4)   aRectangle center                                     "unary" 
      -→ 132@375  

From left to right

Now we know how messages of different kinds or priorities are handled. The final question to be addressed is how messages with the same priority are sent. They are sent from the left to the right. Note that you already saw this behaviour in example 4.3 where the two point creation messages (@) were sent first.

Rule Three. When the messages are of the same kind, the order of evaluation is from left to right.
Example. In the message sends Pen new down all messages are unary messages, so the leftmost one, Pen new, is sent first. This returns a newly created pen to which the second message down is sent, as shown in Figure 4.6.
PIC
Figure 4.6: Decomposing Pen new down

Arithmetic inconsistencies

The message composition rules are simple but they result in inconsistency for the execution of arithmetic message sends expressed in terms of binary messages. Here we see the common situations where extra parentheses are needed.

 
3 + 4 * 5      -→ 35    "(not 23)  Binary messages sent from left to right" 
3 + (4 * 5)    -→ 23 
1 + 1/3         -→ (2/3)    "and not 4/3" 
1 + (1/3)       -→ (4/3) 
1/3 + 2/3       -→ (7/9)    "and not 1" 
(1/3) + (2/3)  -→ 1  
Example. In the message sends 20 + 2 * 5, there are only binary messages + and *. However in Smalltalk there is no specific priority for the operations + and *. They are just binary messages, hence * does not have priority over +. Here the r8t-x-x-85">+. Here than>. They are just binary messages, hence 4.6"> 95">center.
Example 4.3: Example. In the message sends 20 + 2 * down<
  class…">;class�A0;this&#n00A0;to&#vr8c-x-x0A0;to&#amo/span>resulting&#-85">"Binary mem-lmr-10">(65class…-lmr-10">(65class&#="phvr8tBinary <Binary&##x00A0;class�A0;this&#essagese5">"and&#a>this&#es="lstinline">class�fpan>resulting&#-A0;play thelasA0;the&#ofpan>resulting&#sult in in0;play the messages&#xhvalupan>resulting&#-0A0;the sent&#x>.
       &s="lstinline">20 + 2 *  (1) &s="lstinline">20 + 2 -→&##x00A0;2 (2) &##x00A0;2222222 *  -→&11="lstinl/span>1
 <-tex4ht:ref: fig:unaryMessages -->.
   
7n> -x-x-85">@) were436nt first.
) were438nt first.
4r8t-x-xge co">Rulis class="pplb*Th would lead to an error because the object , i >Thfollows di-x-8lyh the same classuxecuto"pplb message se-x-x-clasomeled.samepriceuto"par in Smallindenicx-x-8>Rule phvr8c-x- modeereTo geted in tr-x-8x-xge c,exprehvalusuxere we see th. > does not understand the message 20 +&(#x00A0;2 *&#)lstinline">new<8t-x-xge cophvr8t-x-x-8ote that you already saw this b >4.6"> .
Example 4.3: Example. In the message sends 20 +&(#x00A0;2 *&#)lstinline">down< >
  the messages&#xurroulasupan>resulting&#-A0;play&#e we see thpan>resulting&#su0A0;the&#essagese5">"and&#a>this…">in 0A0;the messages�A0;this sent&#vr8c-0;this to&##x00A0;class&#first0;sent&#vroducthpan>resulting the&# tr-x-8pan>resulting&#-the righ0;.
     &s="lstinline">20 +&(#x00A0;2 *&#)lstinlin="label"> (1)       &(#x00A0;2 *&#)lstinlin="label"> -→&1="lstinline">20 (2)&s="lstinline">20 +&1="lstinline">202020202020 -→&#="lstinl/span>1
 
-x-x-85">@) were451nt first.
>) were454nt first. <- x-x-85">@) were456nt first.

+ and *in 0span>. They are just binary messages, hence * does not have priority over
"> 
"x-x-85">@) were461nt first.

Figure&Equivalindeass="phvru4.6: e we see th. ne">down< 24br
>) were470nt first. <- ) were472nt first. < They are tifferdown"<">down4rr8t-s class="pplb8tw-x-iguhfollowx00y ame classpan equivalind class="pplb8tify ame classwvalusclasexivr8tBoth class="pplb8tsage compoule Thre e="nctNow 85">neRule Threessagetuations w74nt first. <-tex4ht:ref: fig:unaryMessages -->.
">  <8-69n>
"x-x-85">@@ inal-align:bases no;"x00A0TBL-6-1- />td style="white-"> inal-align:bases no;"x00A0TBL-6-2- />td style="white-">td style="white-"> inal-align:bases no;"x00A0TBL-6-3- />td style="white-">td style="white-"> inal-align:bases no;"x00A0TBL-6-4- />td style="white-">td style="white-"> inal-align:bases no;"x00A0TBL-6-5- />td style="white-">td style="white-"> inal-align:bases no;"x00A0TBL-6-6- />td style="white-">
Figure&Mclass="pplb8t-x-x-85ir fullyre we see izen equivalindsne">down< 25br
>) were494nt first. <- > 
tx-lemark 4.4  "<">down"down
50a>Arithmetic inconsistencies does not have priority over + and tN weah. >ithmposuchopnN wea, a.-85">"< class="iw<8t-xlon"+ and does not have priority over * does not have priority over does not have priority over + and """<">down"<">down+ and + and
 
 
20202020" 
2020202020202020202020
 
20202020202020202020(2)&sA0; 
2020202020202020202020(1) 
202020201  
@
) were520nt first.

and tN weah. >ithmp suchopnN wea, a.-85">"< class="iw<8t-xlon" and and """< class="lonal hvr8t-x wea def85"it ation is from left to right.class> -57007r7Hinds/span>
f youss="phvrobhams l qu e mse erecedn>+ and 20"<">down does not understand the message
 "20(1) 9br />1
 5, there are only binary messages + and "<">down
>) were533re extra parentheses are needed.
  ""(1) 2020201
 +. Here the
r8t-x-x-85">+x0cludes:ifTrue:lstinline">
543s="pirst.
. Honnipl="iw<8tre yousehvalusuxer+. Here the r8t-x-x-85">+[/span>20&#ethe exher/span>&#ethe exher/span><, firstsmay be essagese5=any number-8>Ruimas (poexhblyrzero), depex-x00yopan cc>Figxtspan nThey are a-8othe exhersca-8oian sbssa class="pplb, a.variabha, a.literal, a- n ignms="po>*a blonktuations 547nt first. Fdiiv>+ and * does not have priority over does not have priority over &#ethe exher/span>&#ethe exhern>
will .class> -5n>
bssessagese58ote-8lyho>
 2020202020202020202020  the&#-xceiclaA0;the&#andngs-nested"> the&#asgums="A0;the&#mu/s0;this&#-0A0;the&#blonksspan>&#-85">.
 202020202020202020202020202020202020202020202020 the&#asgums="A0;the�A0;this&#essagese5">"and&#mn 0A0;thethe&#o>&#m-lmr-10">(65class&#s00A0;to&#mu/s0;this&#-0A0;the&#alstinlinclass> andhvro8t-x-x-85">the&#blonkspan>&#-85">.
 "20(2)&ifTrue:lstinlin/spanriority over 202020202020202020202020202020 the�A0;this&#essagese5">"and&#o>&#m-lmr-10">(65class&#s00A0;to�A0;this&#nos0;this&#alstinlinclass> andhvro8t-x-x-85">the&#blonkspan>&#-85">.1
  
tx-lemark 4.5 an class > < -x-x-85lfollowx00yethe exher. iesnee5=bycallo8t-x the exhere excepto8t-xlast on-x we ignn 0d.< They are tifcperiod iw਍gure6100r />in 0sa f85al period iw
 202020 2020 2020 -→&truespan>1
  
tx-lemark 4.6 an class > down5<)se-x-x-clacvr8e-x-85l >਍gure6200r />
-5n>@