First time here? Check out the FAQ!

When do I use (...) or [...] in ifTrue:ifFalse ?

0 votes

If I'm trying to protect myself from a divide by zero error I've found I need to use a block enclosure "[...]" in my ifTrue:IfFalse arguments.

pan := (count > 1) ifTrue: [ (i- 1) / (count - 1) ] ifFalse: [0.5].

If I don't put the ifTrue: argument in a block enclosure then it seems it gets evaluated whether (count > 1) is true or false even if it's not left on the stack at run-time, so I get a divide by zero error. It's Smalltalk and ifTrue:ifFalse: are supposed to have blocks as arguments so although I don't understand what's happening without the block enclosure it's not completely unexpected that something odd might happen. 

But in another example, inside my Sound that I'm encapsulating I have this statement in a parameter:

{?rapidRetrigger varIfTrue: (?duration hz samp - 2 samp) ifFalse: (?duration hz)}

which is in a parameter field that expects an array, hence the {...}'s. The ?duration variable is set by a script to the right. What I found is that if I enclose the varIfTrue: argument in [...]'s then something goes odd with the variable. I get prompted to supply the ?duration variable when I run the Sound and the script doesn't set it. If instead I use (...)'s then it works fine. 

Is there some different between ifTrue:ifFalse and varIfTrue:ifFalse, or is it something to do with compilation order or some other rule about when to use a block enclosure and when not?



asked Jul 30, 2019 in Capytalk & Smalltalk by alan-jackson (Virtuoso) (13,410 points)

1 Answer

0 votes

Hi Alan,

As you already guessed, in Smalltalk, you should always use the square brackets with ifTrue:ifFalse: or varIfTrue:ifFalse:

Expressions within square brackets are not evaluated immediately; in the case of ifTrue:ifFalse: and varIfTrue:ifFalse:, only the expression corresponding to the value of the Boolean receiver will be evaluated and the other will not be evaluated. That is what you are relying on in your first example.

Without the square brackets, both alternatives are evaluated and then one is selected. We recommend that you not rely on this behavior since it depends on behavior specific to the version of the Smalltalk interpreter that Kyma is using.

In your second example, as you suspected, has to do with the order of evaluation: ?rapidRetrigger gets substituted by the Script, but green variables inside blocks are not visible to the Script because the evaluation of the blocks occurs later.

An alternative way to implement your secound example could be:

{?duration hz - (?rapidRetrigger varIfTrue: (2 samp) ifFalse: (0))}

This moves ?duration out of the block and so it is visible to the Script at the same time as ?rapidRetrigger.

answered Jul 31, 2019 by ssc (Savant) (106,860 points)