Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Case Expressions and Classes

24 views
Skip to first unread message

Daniel Schierbeck

unread,
Aug 19, 2005, 10:50:45 AM8/19/05
to
Could anyone explain to me why this isn't working?

# returns 'no'
case :foo.class
when Symbol then
puts 'yes'
else
puts 'no'
end

... when this does

# returns 'yes'
case :foo.class.object_id
when Symbol.object_id then
puts 'yes'
else
puts 'no'
end

I'm puzzled...


Thank you in advance,
Daniel Schierbeck

James Edward Gray II

unread,
Aug 19, 2005, 10:56:51 AM8/19/05
to
On Aug 19, 2005, at 9:51 AM, Daniel Schierbeck wrote:

> Could anyone explain to me why this isn't working?
>
> # returns 'no'
> case :foo.class
> when Symbol then
> puts 'yes'
> else
> puts 'no'
> end

Cases use ===() to do the check in when. The ===() for class checks
to see if the passed object is of that class. The object you are
using in the case above is Symbol, which is an object of the class
Class, not the class Symbol you are testing for.

Put another way, you're outsmarting Ruby's very intelligent case
statement. Let it do all the work:

# returns 'yes'
case :foo
when Symbol


puts 'yes'
else
puts 'no'
end

Hope that helps.

James Edward Gray II

David A. Black

unread,
Aug 19, 2005, 10:57:07 AM8/19/05
to
Hi --

On Fri, 19 Aug 2005, Daniel Schierbeck wrote:

> Could anyone explain to me why this isn't working?
>
> # returns 'no'
> case :foo.class
> when Symbol then
> puts 'yes'
> else
> puts 'no'
> end
>

> .... when this does


>
> # returns 'yes'
> case :foo.class.object_id
> when Symbol.object_id then
> puts 'yes'
> else
> puts 'no'
> end
>
> I'm puzzled...

:foo.class is Symbol. In your first case statement, you're asking
whether Symbol is an instance of... Symbol. It isn't: it's an
instance of Class.

What you want is:

case :foo
when Symbol # i.e., if an instance of Symbol

etc.

The second case statement gives you 'yes' because the numbers match,
and the way numbers get compared in case statements isn't affected by
where those numbers come from.


David

--
David A. Black
dbl...@wobblini.net


Patrick Fernie

unread,
Aug 19, 2005, 10:57:14 AM8/19/05
to
With the case...when construct, the class of the object is already
being checked. Therefore, your first form should be:
case :foo

when Symbol then
puts 'yes'
else
puts 'no'
end

By adding the .class to the :foo, the construct is actually checking
the class of :foo.class, which is Class, so you fall through to the
'no' case.

-Patrick

On 8/19/05, Daniel Schierbeck <daniel.s...@gmail.com> wrote:
> Could anyone explain to me why this isn't working?
>
> # returns 'no'
> case :foo.class
> when Symbol then
> puts 'yes'
> else
> puts 'no'
> end
>

> .... when this does

Gavin Kistner

unread,
Aug 19, 2005, 10:59:17 AM8/19/05
to
On Aug 19, 2005, at 8:51 AM, Daniel Schierbeck wrote:
> Could anyone explain to me why this isn't working?
>
> # returns 'no'
> case :foo.class
> when Symbol then
> puts 'yes'
> else
> puts 'no'
> end

Case statements use ===, not == to compare the value against
arguments. The Class#=== operator matches against the class of an
object, so you want:

case :foo


when Symbol then puts 'yes'
else puts no
end

I know, it's sort of confusing. :|

Daniel Schierbeck

unread,
Aug 19, 2005, 11:07:18 AM8/19/05
to

That worked like a charm! Thank you very much!


Daniel Schierbeck

Ara.T.Howard

unread,
Aug 19, 2005, 11:06:20 AM8/19/05
to
On Fri, 19 Aug 2005, Daniel Schierbeck wrote:

> Could anyone explain to me why this isn't working?
>
> # returns 'no'
> case :foo.class
> when Symbol then
> puts 'yes'
> else
> puts 'no'
> end
>

> .... when this does


>
> # returns 'yes'
> case :foo.class.object_id
> when Symbol.object_id then
> puts 'yes'
> else
> puts 'no'
> end
>
> I'm puzzled...
>
>
> Thank you in advance,
> Daniel Schierbeck

case statements use the '===' operator. the '===' for classes is the same as
'is_a?' for classes. so writing

with case statements the obj of the statement is used as the argument for the
'===' operator of each case, so

case obj
when Foo
...
when Bar
end

is the same as

if Foo === obj
...
elsif Bar === obj
...
end

and

case string
when %r/foo/
...
when %r/bar/
end

is the same as

if %r/foo/ === string
...
elsif %/bar/ === string
...
end

so what you've written:

case Symbol
when Symbol
'yes'
else
'no'
end

is the same as

if Symbol === Symbol
'yes'
else
'no'
end

so, '===', when applied to a class, tests if an object is an __instance__ of
that class. so

String === 'a string' #=> true
Array === [42] #=> true

therefore, you are asking if Symbol is an instance of a Symbol - which it is
not. it __is__ equalivalent to Symbol, but that would mean '==' and not
'==='.

case statements can also do this

case obj
when String, Fixnum, Array
when File
when %r/foo/, %r/bar/
else
end

where each element in the list applies '===' to the argument 'obj' to see when
line triggers - it's really powerful.

hth.


-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| Your life dwells amoung the causes of death
| Like a lamp standing in a strong breeze. --Nagarjuna
===============================================================================

0 new messages