December 11, 2023

Smalltalk Precedence Rules


The Smalltalk system evaluates messages in an order determined by a set of precedence rules.

These are:

  1. Evaluate anything in brackets first, work from left to right
  2. Unary expressions are evaluated left to right before (take precedence over) binary expressions
  3. Binary expressions are evaluated left to right before (take precedence over) keyword expressions
  4. Keyword expressions are evaluated last, again working left to right
  5. Warning! Although usually sufficient for most purposes, these rules occasionally lead us astray.

The precedence rules do not always accurately reflect the order of evaluation as implemented by the Smalltalk parser, the software that 'reads' the code. The parser works strictly left to right, but before evaluating a message it looks ahead to the next message to check if it is of a higher precedence than the current message. If the next message is of higher precedence then it gets evaluated before the current message. The precedence tool provided in LearningWorks uses the same rules as the parser and works well as long as brackets are not used. It works reliably for evaluating expressions that are combinations of binary, unary and keywords, but you should avoid using it with bracketed expressions.

Consider the following:

aFrog right position:(aFrog position)

If you follow the precedence rules you will evaluate the bracketed message first. This will lead you to a wrong evaluation. The parser evaluates aFrog right first, since parsing left to right will determine right as the first unary message. If aFrog is a newly created instance with position of 1 then the above expression will set its position to 2 not 1.

Now consider this code:

10 + (10 negated) negated

The precedence tool finds + realises it must look ahead one for a message of higher precedence. In the look ahead it instead finds the brackets and correctly evaluates the contents of those brackets. It then 'forgets' that it still hasn't completed the original search for a message of higher precedence and incorrectly evaluates the binary message (10 + -10) before sending negated to 0. The tool leads you to an incorrect answer of 0. The correct result of the message expression should of course be 20.

Consider some other examples.

(25 + 3 * 4 ) printString

  1. Reading left to right, the nested expression (25 + 3 * 4) is evaluated first
  2. Reading left to right, 25 receives the binary message + 3
    The message answer returned is the object 28
  3. 28 receives the binary message * 4
    The message answer is the object 112.
  4. 112 now receives the unary message printString
    The message answer is the string '112'

What happens if you try and evaluate 25 + 3 * 4 printString ?
This will cause a system error.

  1. Reading from left to right, the parser is able to determine that 25 is a receiver for a + 3 message
    This returns 28
  2. Reading left to right, the absence of brackets causes Smalltalk to evaluate the expression 4 printString
    This returns the string object '4'
  3. 28 now receives the binary message * '4'
    This message is not understood by Smalltalk since the argument to the selector * should be a number object and not a string, hence the system error

Here is another example.

'The ' , ((25 plus: 3 * 4) + 2) printString , ' Steps'

  1. Reading left to right, the parser drills down to innermost brackets and evaluates the nested expression 25 plus: 3 * 4
  2. Reading left to right, the binary expression 3 * 4 returns the number object 12
  3. 12 is now supplied as the argument to the keyword selector plus: and the message plus: 12 is sent to the number object 25 and returns 37
  4. Smalltalk can now evaluate (37 + 2).
    37 receives the binary message + 2 and returns the message answer 39
  5. Smalltalk evaluates 'The ' , 39 printString , ' Steps' .
    Reading from left to right the unary expression 39 printString takes precedence and returns the string object '39' as its message answer.
  6. Reading from left to right, the string '39' is passed as the argument to the binary selector ,
    Consequently 'The ' receives the binary message , '39' which returns the message answer 'The 39'
  7. 'The 39' receives a binary message , ' Steps'
  8. The final message answer is the string 'The 39 Steps'

Go here for some precedence questions and answers.

Next page » Dialog

Previous page « Print-strings
































































Up to top of page