Smalltalk - Compare two strings for equality
Asked Answered
G

6

9

I am trying to compare two strings in Smalltalk, but I seem to be doing something wrong.

I keep getting this error:

Unhandled Exception: Non-boolean receiver. Proceed for truth.

stringOne := 'hello'.
stringTwo := 'hello'.
myNumber := 10.

[stringOne = stringTwo ] ifTrue:[
   myNumber := 20].

Any idea what I'm doing wrong?

Glenglencoe answered 29/10, 2009 at 2:28 Comment(0)
L
17

Try

stringOne = stringTwo 
     ifTrue: [myNumber := 20]`

I don't think you need square brackets in the first line

Found great explanation. Whole thing is here

In Smalltalk, booleans (ie, True or False) are objects: specifically, they're instantiations of the abstract base class Boolean, or rather of its two subclasses True and False. So every boolean has type True or False, and no actual member data. Bool has two virtual functions, ifTrue: and ifFalse:, which take as their argument a block of code. Both True and False override these functions; True's version of ifTrue: calls the code it's passed, and False's version does nothing (and vice-versa for ifFalse:). Here's an example:

a < b
  ifTrue: [^'a is less than b']
  ifFalse: [^'a is greater than or equal to b']

Those things in square brackets are essentially anonymous functions, by the way. Except they're objects, because everything is an object in Smalltalk. Now, what's happening there is that we call a's "<" method, with argument b; this returns a boolean. We call its ifTrue: and ifFalse: methods, passing as arguments the code we want executed in either case. The effect is the same as that of the Ruby code

if a < b then
  puts "a is less than b"
else
  puts "a is greater than or equal to b"
end
Lupelupee answered 29/10, 2009 at 2:35 Comment(3)
Thanks my fellow Android. That was the problem.Glenglencoe
Woof - I'm not that familiar w Smalltalk but I sorta remembered that square brackets are for evaluation and if you evaluate = operator you are not going to get a boolean :)Lupelupee
sigh - wanted to add acode example here, but it was misformatted. Forget it, I added an answer...Sadoff
M
5

As others have said, it will work the way you want if you get rid of the first set of square brackets.

But to explain the problem you were running into better:

[stringOne = stringTwo ] ifTrue:[myNumber := 20]

is passing the message ifTrue: to a block, and blocks do not understand that method, only boolean objects do.

If you first evaluate the block, it will evaluate to a true object, which will then know how to respond:

[stringOne = stringTwo] value ifTrue:[myNumber := 20]

Or what you should really do, as others have pointed out:

stringOne = stringTwo ifTrue:[myNumber := 20]

both of which evaluates stringOne = stringTwo to true before sending ifTrue:[...] to it.

Morass answered 29/10, 2009 at 3:3 Comment(0)
V
1

[stringOne = stringTwo] is a block, not a boolean. When the block is invoked, perhaps it will result in a boolean. But you are not invoking the block here. Instead, you are merely causing the block to be the receiver of ifTrue.

Instead, try:

(stringOne = stringTwo) ifTrue: [
    myNumber := 20 ].
Vandalize answered 29/10, 2009 at 2:37 Comment(0)
P
0

Should you be blocking the comparison? I would have thought that:

( stringOne = stringTwo ) ifTrue: [ myNumber := 20 ]

would be enough.

Potty answered 29/10, 2009 at 2:36 Comment(1)
The parens there are both unnecessary and atypical. In fact, I find that if I'm writing expressions that need parens (especially nested parens), I'm probably making things too complicated, and refactor it out to a named temp or separate method call.Terchie
P
0

but I seem to be doing something wrong

Given that you are using VisualWorks your install should include a doc folder.

Look at the AppDevGuide.pdf - it has a lot of information about programming with VisualWorks and more to the point it has a lot of introductory information about Smalltalk programming.

Look through the Contents table at the beginning, until Chapter 7 "Control Structures", click "Branching" or "Conditional Tests" and you'll be taken to the appropriate section in the pdf that tells you all about Smalltalk if-then-else and gives examples that would have helped you see what you were doing wrong.

Pouched answered 30/10, 2009 at 18:2 Comment(0)
S
0

I would like to add the following 50Cent:

as blocks are actually lambdas which can be passed around, another good example would be the following method:

do:aBlock ifCondition:aCondition
    ... some more code ...
    aCondition value ifTrue: aBlock.
    ... some more code ...
    aBlock value
    ...

so the argument to ifTrue:/ifFalse: can actually come from someone else. This kind of passed-in conditions is often useful in "..ifAbsent:" or "..onError:" kind of methods.

(originally meant as a comment, but I could not get the code example to be unformatted)

Sadoff answered 11/5, 2011 at 7:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.