Smalltalk Message Rules

The basic rules for messages/methods in Smalltalk Language are:

Unary messages: Take no arguments.

Dictionary ''new''. 12 ''factorial''.

Binary messages: Take exactly one argument and use one or more non-alphabetic symbols for the selector.

+ 7.

'BIG' ''>'' 'little'

Keyword messages: Take one or more arguments and use words followed by colon before each argument.

between: 1 and: 10.

Transcript ''show:'' aString. 12 > 7 ''ifTrue:'' ['yes'] ''ifFalse:'' ['no'].


Precedence rules: Left to right, Unary then binary then keyword.

3 squared + 4 squared between:
1 and: 1000.

Executes 3 squared then 4 squared then 9 + 16 then 25 between:
1 and: 1000
.

Method signatures: Methods are identified by the symbol which is their selector:

#new, #factorial, #+, #>, #between:and:, #show:, #ifTrue:ifFalse:


Can anyone explain how the messaging notation works when combined with the ; cascading operator? I.e. I have something like:

7 + 3 squared; printOn:
aStream

What's printed now? 3 or (7 + 3 squared)?

-- Stephan Houben (trying to write a YACC grammar of Smalltalk, just for the heck of it).

The meaning of semi-colon is, "Send the next message to the same object that received the previous message". A simpler example would be:

aStream nextPutAll: 'line 1'; cr; nextPutAll: 'line 2'.

So in this case, cr is sent to the same object that received the first nextPutAll:, namely aStream. Same goes for the last nextPutAll:.

Your example is a bit trickier, though, because of the precedence rules:

7 + 3 squared; printOn:
aStream

3 squared gets evaluated first. Then 7 + 9, then 7 printOn:
aStream
.

Here's a couple more examples:

+ 4 squared; factorial; yourself.

''4 squared'', then ''7 + 16'', then ''7 factorial'' then ''7 yourself'' -> 7.

+ 2 squared factorial; yourself.

''2 squared'', then ''4 factorial'' then ''7 + 24'', then ''7 yourself'' -> 7.


I find it quite easier "parse" the above examples like this (it avoids english :)

+ 4 squared; factorial; yourself.

+ 2 squared factorial; yourself.


Q: Can anyone explain how Smalltalk implements shortcut evaluation of logical operators? E.g. is this possible?

((x != 0) && ((n / x) > 10)) ifTrue:
[ .... ].

Apologies if the operators are not correct -- I'm interested in the semantics, rather than the precise syntax. -- anon

A: That is a form of deferred evaluation, which in Smalltalk is always done with blocks. The example becomes:

(x ~= 0 and:
[n / x > 10]) ifTrue: [ .... ].

The first part, x ~= 0, returns true or false which are normal objects. When true is sent #and:, it evaluates the second argument (the block [n / x > 10]) with #value and returns that. When false is sent #and:, it just returns false without evaluating the second argument.

Thus what is done in Cee Plus Plus with special language magic is done in Smalltalk with the general mechanisms of blocks and polymorphism. One consequence is that you can write your own short-cut methods which behave like the built-in ones. In C++, you can overload operator&&() but you cannot duplicate the short-cut arguments.

Previous edit of this page was 2005 -- in 2012, C++ finally has deferred evaluation with lambdas, so you could write this as:

Iftrue(And(x != 0, [=]{ return (n / x) > 10 }), [=]{ ... })

What? I didn't say the future was *pretty*


See original on c2.com