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

R

Ruby Rabbit

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
 
P

Peña, Botp

RnJvbTogUnVieSBSYWJiaXQgW21haWx0bzpzZW50aW5lbC4yMDAxQGdteC5jb21dIA0KIyBjPTIz
LmNsYXNzICAjID0+IEZpeG51bQ0KIyBjID09IEZpeG51bSAjICA9PiB0cnVlDQojIGNhc2UgYzsg
d2hlbiBGaXhudW07IHB1dHMgIllFUyI7IGVsc2U7IHB1dHMgIk5PIjsgZW5kDQojIA0KIyAjID0+
IHByaW50cyBOTw0KIyAjIGFmdGVyIG11Y2ggaGVhZC1zY3JhdGNoaW5nIHRyaWVkIHRoaXM6DQoj
DQojIGNhc2UgYzsgd2hlbiBGaXhudW07IHB1dHMgIllFUyI7IHdoZW4gQ2xhc3M7IHB1dHMgIkNM
QVNTIjsgZWxzZTsgcHV0cw0KIyAiTk8iOyBlbmQNCiMgIyBwcmludHMgQ0xBU1MNCg0KDQpjYXNl
IHVzZXMgPT09OyB0aHVzIG9uIHlvdXIgY2FzZSwgaXQgc2hvdWxkIGJlIGVhc2llci4uLg0KDQpl
ZyB0cnksDQoNCj4gYz0yMw0KPT4gMjMNCg0KPiBjYXNlIGM7IHdoZW4gRml4bnVtOyBwdXRzICJZ
RVMiOyBlbHNlOyBwdXRzICJOTyI7IGVuZA0KDQpZRVMNCj0+IG5pbA0KDQo+IGM9ImhlbGxvIg0K
PT4gImhlbGxvIg0KDQo+IGNhc2UgYzsgd2hlbiBGaXhudW07IHB1dHMgIllFUyI7IHdoZW4gU3Ry
aW5nOyBwdXRzICJZRVMgU1RSSU5HISI7ICBlbHNlOyBwdXRzICJOTyI7IGVuZA0KDQpZRVMgU1RS
SU5HIQ0KPT4gbmlsDQoNCg==
 
S

Stefano Crocco

Alle Wednesday 07 January 2009, Ruby Rabbit ha scritto:
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.

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 (c) 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
 
J

Justin Collins

Ruby said:
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.
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
 
R

Ruby Rabbit

Stefano said:
Alle Wednesday 07 January 2009, Ruby Rabbit ha scritto:

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.
 

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
473,754
Messages
2,569,527
Members
45,000
Latest member
MurrayKeync

Latest Threads

Top