Using case with classes

Ok, this did not work like I expected (because I know too little about
Ruby):

def test( obj )
case obj.class
when Array then puts "Array"
when Hash then puts "Hash"
when Class then puts "Class"
else puts "ugh"
end
end

irb(main):009:0> test Array.new
Class
=> nil
irb(main):010:0> test Hash.new
Class
=> nil
irb(main):011:0> test Class.new
Class
=> nil

Hmmm. Ok. So I figured out that case/when uses === and not ==. I’m
sure there is for a good reason but…why?

irb(main):012:0> Array === Array
=> false
irb(main):013:0> Class === Class
=> true

So it turns out that === for Class checks if the rvalue is an instance
of the lvalue and === of Object is a just ==. Is this right? Obviously
Array is not an instance of Array, but not so obviously, Class IS an
instance of Class. This makes sense but my brain is starting to hurt.
So I can write ‘test’ this way:

def test( obj )
case obj # <---- removed the '.class’
when Array then puts "Array"
when Hash then puts "Hash"
when Class then puts "Class"
else puts "ugh"
end
end

irb(main):022:0> test Array.new
Array
=> nil
irb(main):023:0> test Hash.new
Hash
=> nil
irb(main):024:0> test Class.new
Class
=> nil

Werid. Can someone help me figure out the === operator? When should I
be redefining it? In what cases should I be using it?

Michael

Michael Garriss wrote:

Ok, this did not work like I expected (because I know too little about
Ruby):

def test( obj )
case obj.class
when Array then puts “Array”
when Hash then puts “Hash”
when Class then puts “Class”
else puts “ugh”
end
end

irb(main):009:0> test Array.new
Class
=> nil
irb(main):010:0> test Hash.new
Class
=> nil
irb(main):011:0> test Class.new
Class
=> nil

Hmmm. Ok. So I figured out that case/when uses === and not ==. I’m
sure there is for a good reason but…why?

irb(main):012:0> Array === Array
=> false
irb(main):013:0> Class === Class
=> true

So it turns out that === for Class checks if the rvalue is an instance
of the lvalue and === of Object is a just ==. Is this right?
Obviously Array is not an instance of Array, but not so obviously,
Class IS an instance of Class. This makes sense but my brain is
starting to hurt. So I can write ‘test’ this way:

def test( obj )
case obj # <---- removed the ‘.class’
when Array then puts “Array”
when Hash then puts “Hash”
when Class then puts “Class”
else puts “ugh”
end
end

irb(main):022:0> test Array.new
Array
=> nil
irb(main):023:0> test Hash.new
Hash
=> nil
irb(main):024:0> test Class.new
Class
=> nil

Werid. Can someone help me figure out the === operator? When should
I be redefining it? In what cases should I be using it?

Michael

Looking at the Ruby Class/Library reference at:

http://www.rubycentral.com/ref/

Which might not be updated for 1.8, but whatever…

=== is the case equality operator. So you should redefine it to make
your class act appropriately in case statements.

For example, the Range class redefines it so that Range === obj tests
to see if obj is contained in range, so you can do:

case 50
when 1…10 then foo
when 11…100 then bar
end

For Regexps, === is the same as =~.

Most of the time === is the same as ==, but Module redefines === to mean
is rvalue an instance of lvalue, or
of a descendant of lvalue, which is where Class gets it from, I assume.

Hope this helps.

  • Dan

try this:

def test( obj )
    case obj
       when Array then puts "Array"
       when Hash  then puts "Hash"
       when Class then puts "Class"
       else puts "ugh"
    end
end

Unfortunately the behavior above is still annoying; in this case you
have an object to work with, but I’ve run into a number of cases
where I have only a class, and I just have to use a big “if” block.

···

On Tue, 12 Aug 2003 10:25:04 +0900 Michael Garriss mgarriss@earthlink.net wrote:

Ok, this did not work like I expected (because I know too little about
Ruby):

def test( obj )
case obj.class
when Array then puts “Array”
when Hash then puts “Hash”
when Class then puts “Class”
else puts “ugh”
end
end


Ryan Pavlik rpav@users.sf.net

“These burnt fries are comin’ out of your check
Mr. Ninja!” - 8BT

def test( obj )
    case obj
       when Array then puts "Array"
       when Hash  then puts "Hash"
       when Class then puts "Class"
       else puts "ugh"
    end
end

How about

def test(obj)
if [Array, Hash, Class].include?(obj.class) then
puts obj.class.to_s
else
puts “ugh”
end
end

I suspect that the case statement may be faster.

Scott

“Ryan Pavlik” rpav@users.sourceforge.net schrieb im Newsbeitrag
news:20030811190930.5e03fb72.rpav@users.sf.net

Ok, this did not work like I expected (because I know too little about
Ruby):

def test( obj )
case obj.class
when Array then puts “Array”
when Hash then puts “Hash”
when Class then puts “Class”
else puts “ugh”
end
end

try this:

def test( obj )
    case obj
       when Array then puts "Array"
       when Hash  then puts "Hash"
       when Class then puts "Class"
       else puts "ugh"
    end
end

Unfortunately the behavior above is still annoying; in this case you
have an object to work with, but I’ve run into a number of cases
where I have only a class, and I just have to use a big “if” block.

No.

class TypeCheck
def initialize(cl)
@cl = cl
end

def ===(o)
@cl == o
end
end

case Array
when TypeCheck.new(Array)
puts “Array”
when TypeCheck.new(Hash)
puts “Hash”
else
puts “buh!”
end

even better, because it creates less instances:

def TypeCheck(cl)
(@@checks ||= Hash.new {|h,k| h[k] = TypeCheck.new(k)} )[cl]
end

case Array
when TypeCheck(Array)
puts “Array”
when TypeCheck(Hash)
puts “Hash”
else
puts “buh!”
end

see also ruby talk 76641

robert
···

On Tue, 12 Aug 2003 10:25:04 +0900 > Michael Garriss mgarriss@earthlink.net wrote:

def test( obj )
    case obj
       when Array then puts "Array"
       when Hash  then puts "Hash"
       when Class then puts "Class"
       else puts "ugh"
    end
end

How about

def test(obj)
if [Array, Hash, Class].include?(obj.class) then
puts obj.class.to_s
else
puts “ugh”
end
end

I suspect that the case statement may be faster.

How about

def test(obj)
puts
case obj
when Array, Hash, Class then obj.class
else; “ugh”
end
end

?

Gavin

Gavin Sinclair wrote:

def test( obj )
case obj
when Array then puts “Array”
when Hash then puts “Hash”
when Class then puts “Class”
else puts “ugh”
end
end

How about

def test(obj)
if [Array, Hash, Class].include?(obj.class) then
puts obj.class.to_s
else
puts “ugh”
end
end

I suspect that the case statement may be faster.

How about

def test(obj)
puts
case obj
when Array, Hash, Class then obj.class
else; “ugh”
end
end

?

Gavin

Very nice, but why the ‘;’ after ‘else’? Works with and without for me.

Michael

def test(obj)
puts
case obj
when Array, Hash, Class then obj.class
else; “ugh”
end
end

?

Gavin

Very nice, but why the ‘;’ after ‘else’? Works with and without for me.

Michael

I’m pleasantly surprised. Another semicolon bites the dust.

Gavin