=== confusion


(Ian Macdonald) #1

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
ian@caliban.org | content. – Niccolo Machiavelli
http://www.caliban.org |
>


(George Ogata) #2

Ian Macdonald ian@caliban.org writes:

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 ofClass’, 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