Why ifTrue and ifFalse are not separated by ; in 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 ob开发者_JS百科jectInstance. Is not the same with the above conditional execution?
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:
.
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...
精彩评论