=== confusion

I

Ian Macdonald

Hello,

After a couple of years of Ruby programming, I find that the ===
operator still has the ability to occasionally confound me.

Today, I had some code that looked like this:

foo = case bar.class
when Foo::Bar
'abc'
when Foo::Bar::Baz
'def'
when Foo::Qux
'ghi'
else
'jkl'
end

The problem is that most comparisons of bar.class fell through to the
else clause. A quick debugging session on a particular instance of 'bar'
revealed that 'bar.class == Foo::Bar' was true, but
'bar.class === Foo::Bar' was false. Quite honestly, I don't understand
why, as I'm not overriding === anywhere. My classes are not derived from
any standard Ruby classes, either, so they should be inheriting ===
from Object, if I understand things correctly.

I fixed it by changing the start of the case statement to
'case bar.class.to_s' and then comparing to strings instead of object
identifiers, but I would like to understand what exactly === was doing
in the original case.

Ian
--
Ian Macdonald | When neither their poverty nor their honor
System Administrator | is touched, the majority of men live
(e-mail address removed) | content. -- Niccolo Machiavelli
http://www.caliban.org |
|
 
G

George Ogata

Ian Macdonald said:
foo = case bar.class
when Foo::Bar
'abc'
when Foo::Bar::Baz
'def'
when Foo::Qux
'ghi'
else
'jkl'
end

The problem is that most comparisons of bar.class fell through to the
else clause. A quick debugging session on a particular instance of 'bar'
revealed that 'bar.class == Foo::Bar' was true, but
'bar.class === Foo::Bar' was false. Quite honestly, I don't understand
why, as I'm not overriding === anywhere. My classes are not derived from
any standard Ruby classes, either, so they should be inheriting ===
from Object, if I understand things correctly.

I fixed it by changing the start of the case statement to
'case bar.class.to_s' and then comparing to strings instead of object
identifiers, but I would like to understand what exactly === was doing
in the original case.

This keeps coming up from time to time.

Module#=== returns true iff the argument is an instance of the module
or one of its descendants (from the Pickaxe). In your code,
`bar.class' returns an instance of `Class', which is of course not a
descendant of `Foo::Bar', `Foo::Bar::Baz', etc., and so falls through
to the else clause. I think what you want is to remove the `.class'
in the case expression:

foo = case bar
## ^^^^^^ (removed the `.class')
when Foo::Bar
'abc'
when Foo::Bar::Baz
'def'
when Foo::Qux
'ghi'
else
'jkl'
end

HTH
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,521
Members
44,995
Latest member
PinupduzSap

Latest Threads

Top