MrDuk
MrDuk

Reputation: 18242

Smalltalk ifFalse / ifTrue not working

Can someone explain why this isn't working how I expect?

add: rhsKey
myUnits includesKey: rhsKey
            ifTrue: myUnits put: (myUnits at: rhsKey) + 1 at: rhsKey 
            ifFalse: myUnits add: rhsKey -> 1.

Example execution:

ut := UnitTracker named: 'test'.

ut add: 'seconds'.

ut add: 'seconds'.

ut add: 'seconds'.

ut add: 'minutes'.

It keeps executing through the ifTrue on the first go-round.

Upvotes: 1

Views: 674

Answers (3)

aka.nice
aka.nice

Reputation: 9382

Once you grok the keyword syntax, I advise to study/mimic the at:ifAbsent: message in Dictionary which could be used like this:

myUnits at: rhsKey put: (myUnits at: rhsKey ifAbsent: [0]) + 1  

Upvotes: 2

Stuart Herring
Stuart Herring

Reputation: 899

ifTrue:ifFalse: accepts blocks [ ] as arguments. If you don't encapsulate the code you want run on true and false in a block it will be executed before the call to ifTrue:ifFalse:.

You also need to surround myUnits includesKey: rhsKey in parentheses ( ), because otherwise the compiler will get confused as to which message you're actually trying to send.

In fact, I'm surprised you didn't get a DoesNotUnderstand exception for that code, as you've effectively sent includesKey:ifTrue:put:at:ifFalse:add: to myUnits.

With brackets added as you probably intended, it will look like this:

add: rhsKey
  (myUnits includesKey: rhsKey)
        ifTrue: [ myUnits put: (myUnits at: rhsKey) + 1 at: rhsKey ]
        ifFalse: [ myUnits add: rhsKey -> 1. ]

So now ifTrue:ifFalse: is being sent to the result of myUnits includesKey: rhsKey

Upvotes: 7

Chris Gerken
Chris Gerken

Reputation: 16392

Put brackets around the statements in the true and false blocks.

Upvotes: 2

Related Questions