Could not understand this: 3.class is Fixnum or Class


#1

I stored the class of a variable in a variable and later checked in a
switch-case. Instead of going into the Fixnum case, it goes into ELSE.

c=23.class # => Fixnum

c == Fixnum # => true

case c; when Fixnum; puts “YES”; else; puts “NO”; end

=> prints NO

after much head-scratching tried this:

case c; when Fixnum; puts “YES”; when Class; puts “CLASS”; else; puts
“NO”; end

prints CLASS


As a result of this I had to store the class as a string (to_s), so the
case could work.
Could someone explain what I am missing here.
Thx.


#2

From: Ruby R. [mailto:removed_email_address@domain.invalid]

c=23.class # => Fixnum

c == Fixnum # => true

case c; when Fixnum; puts “YES”; else; puts “NO”; end

# => prints NO

# after much head-scratching tried this:

case c; when Fixnum; puts “YES”; when Class; puts “CLASS”; else; puts

“NO”; end

# prints CLASS

case uses ===; thus on your case, it should be easier…

eg try,

c=23
=> 23

case c; when Fixnum; puts “YES”; else; puts “NO”; end

YES
=> nil

c=“hello”
=> “hello”

case c; when Fixnum; puts “YES”; when String; puts “YES STRING!”; else; puts “NO”; end

YES STRING!
=> nil


#3

Stefano C. wrote:

Alle Wednesday 07 January 2009, Ruby R. ha scritto:

Could someone explain what I am missing here.
Thx.

Stefano

Thanks. Actually both replies side step the issue I have at hand.
I have an incoming variable, I store its class, the variable is
converted to a string. When the class returns the variable, it converts
back.

def set_buffer val
@datatype = val.class
@buffer = val.to_s
end

def get_buffer
case @datatype
when Fixnum
return @buffer.to_i
etc
end

Its like the above.

So, instead of saying

@datatype = val.class.to_s

and later checking for a string, i was trying to store the class and
check against it.

Thanks for clearing up the confusion.


#4

Ruby R. wrote:

Could someone explain what I am missing here.
Thx.

Case statements do not use the equality operator (==), they use the
“relationship operator” (===), which is typically not commutative. Also,
the value in the “when” part is the left-hand value (not the right-hand
value, as you might expect).

Futhermore, Class objects (like Fixnum) use Module’s definition of
“===”, which returns true if the right-hand side is an instance of the
module or one of its descendents.

Therefore:

irb(main):001:0> c = 32.class
=> Fixnum
irb(main):002:0> Fixnum === c
=> false
irb(main):003:0> Fixnum === Fixnum
=> false
irb(main):004:0> Fixnum === 23
=> true

-Justin


#5

Alle Wednesday 07 January 2009, Ruby R. ha scritto:

Could someone explain what I am missing here.
Thx.

The case expression uses the === operator of the objects in the “when”
statements to decide which one needs to be executed. This means that the
expression

case c
when Fixnum then puts “YES”
when Class then puts “CLASS”
else puts “NO”
end

is (more or less) equivalent to the following if expression:

if Fixnum === c then puts “YES”
elsif Class === c then puts “CLASS”
else puts “NO”
end

Now, the documentation for Class#=== (since both Fixnum and Class are
object
of class Class) states that it returns true if an instance of the class
or of
one of its descendents and false otherwise. In other words, cls === obj
returns true if obj.is_a?(cls) returns true and false otherwise. In your
case,
the object you’re testing © is the class of 23, that is Fixnum. So,
when
executing the case expression, ruby does something like this:

Fixnum === c # returns false because c.is_a?(Fixnum), that is
# Fixnum.is_a?(Fixnum) is false
Class === c # returns true because c.is_a?(Class), that is
# Fixnum.is_a?(Class) is true
puts “CLASS”

To get what you want, you have two possibilities:

  1. use “case 23” instead of “case c”. This way, it will work as you
    expected,
    because 23 is an instance of class Fixnum, so Fixnum === 23 returns true
  2. use an if expression instead of a case expression:
    if c.is_a?(Fixnum) then #…
    elsif c.is_a?(Class) then #…
    else #…
    end

I hope this helps

Stefano