Case Expressions and Classes

D

Daniel Schierbeck

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
 
J

James Edward Gray II

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
 
D

David A. Black

Hi --

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
 
P

Patrick Fernie

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
 
G

Gavin Kistner

--Apple-Mail-5-127465413
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
charset=US-ASCII;
delsp=yes;
format=flowed

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. :|

--Apple-Mail-5-127465413--
 
A

Ara.T.Howard

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
===============================================================================
 
D

Daniel Schierbeck

James said:
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

That worked like a charm! Thank you very much!


Daniel Schierbeck
 

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
474,176
Messages
2,570,947
Members
47,501
Latest member
Ledmyplace

Latest Threads

Top