Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why ifTrue and ifFalse are not separated by ; in Smalltalk?

Tags:

smalltalk

a > b
ifTrue:[ 'greater' ]
ifFalse:[ 'less or equal' ]

My understanding is that Boolean a > b receives the message ifTrue:[ 'greater' ], and then ifFalse:[ 'less or equal' ] complying to the generalization:

objectInstance selector; selector2

But there a semicolon is needed to specify that the receiver of selector2 is not (objectInstance selector) but objectInstance. Is not the same with the above conditional execution?

like image 435
simpatico Avatar asked Jun 27 '10 13:06

simpatico


2 Answers

The selector of the method is Boolean>>ifTrue:ifFalse:, which means it is one method with two parameters, not two methods with one parameter.

Ergo, to invoke the method, you send it the message ifTrue:ifFalse: with two block arguments.

Note that for convenience reasons, there are also methods Boolean>>ifFalse:ifTrue:, Boolean>>ifTrue: and Boolean>>ifFalse:.

like image 112
Jörg W Mittag Avatar answered Nov 07 '22 09:11

Jörg W Mittag


Everything relevant has already been sayd, but just for your amusement:

As already told,

rcvr ifTrue:[...] ifFalse:[...]

is the one and single message #'ifTrue:ifFalse:' with 2 args sent to rcvr. The value of that expression is the one from that message send. In contrast:

rcvr ifTrue:[...]; ifFalse:[...]

is a cascade of 2 sequential messages (#'ifTrue:' and #'ifFalse:'), each with 1 arg sent to rcvr. The value of the expression is the one returned from the last send.

Now the funny thing is that booleans do understand ifTrue: / ifFalse: (each with 1 arg), so your code works for the side effect (evaluating those blocks), but not for its value. This means that:

a > b ifTrue:[Transcript showCR:'gt'] ; ifFalse:[Transcript showCR:'le']

generates the same output as:

a > b ifTrue:[Transcript showCR:'gt'] ifFalse:[Transcript showCR:'le']

but:

msg := a > b ifTrue:['gt'] ; ifFalse:['le']

will generate different values in msg than:

msg := a > b ifTrue:['gt'] ifFalse:['le']

depending on the values of a and b. Try (a b)=(1 2) vs. (a b)=(2 1)...

The problem of many Smalltalk beginners is that they think of ifXXX: as syntax, where it is actually a message send which generates value. Also, the semi is not a statement separator as in many previously learned languages, but a sequencing message send construct.

A bad trap for beginners, because the code seems to work for some particular value combinations, whereas it generates funny results for others. Let's hope your unit tests cover these ;-)

edit: to see where the bad value comes from, take a look at what is returned by the Boolean >> ifFalse: method for a true receiver...

like image 9
blabla999 Avatar answered Nov 07 '22 08:11

blabla999