what on earth..

J

Joe Van Dyk

a =3D 5
puts Fixnum =3D=3D a.class # spits out true

# spits out "Who knows what I am. :-("
case a.class
when Fixnum
puts "I'm a fixnum!"
else
puts "Who knows what I am. :-("
end


What's going on here?

Joe
 
B

burke

Joe said:
a = 5
puts Fixnum == a.class # spits out true

# spits out "Who knows what I am. :-("
case a.class
when Fixnum
puts "I'm a fixnum!"
else
puts "Who knows what I am. :-("
end


What's going on here?

Joe

I'll admit I only started learning Ruby 3 days ago, so don't hold it
against me if I misguide you ;), but I believe switch uses '===' to
compare, which I think is a more precise match...

5.class == Fixnum => true
5.class === Fuxnum => false

You might want to just use ifs instead.

Burke
 
T

Timothy Bennett

case uses === for comparison, not ==

In my irb, Fixnum === 5.class => false

As for why === gives false, I have no idea. In the mean time, you
could use

case a.class.to_s
when "Fixnum"
puts ....
else
puts ....
end

Tim
 
M

Mike Stok

a = 5
puts Fixnum == a.class # spits out true

# spits out "Who knows what I am. :-("
case a.class
when Fixnum
puts "I'm a fixnum!"
else
puts "Who knows what I am. :-("
end


What's going on here?

case doesn't use == you can do this:

a = 5

case a
when Fixnum
puts "I'm a fixnum"
else
puts "other"
end

and by coincidence (not)

ratdog:~/tmp mike$ irb
irb(main):001:0> a = 5
=> 5
irb(main):002:0> Fixnum === a
=> true

ratdog:~/tmp mike$ ri Module#===
------------------------------------------------------------- Module#===
mod === obj => true or false
------------------------------------------------------------------------
Case Equality---Returns +true+ if _anObject_ is an instance of
_mod_ or one of _mod_'s descendents. Of limited use for modules,
but can be used in +case+ statements to classify objects by class.


Hope this helps,

Mike

--

Mike Stok <[email protected]>
http://www.stok.ca/~mike/

The "`Stok' disclaimers" apply.
 
B

burke

burke said:
5.class === Fuxnum => false

Umm, ok. Obviously it's not a Fuxnum. I think I should clear that up:

5.class === Fixnum => false
as well. haha... Sorry about that.

Burke
 
T

Timothy Bennett

case doesn't use == you can do this:
a = 5

case a
when Fixnum
puts "I'm a fixnum"
else
puts "other"
end


ratdog:~/tmp mike$ ri Module#===
-------------------------------------------------------------
Module#===
mod === obj => true or false
----------------------------------------------------------------------
--
Case Equality---Returns +true+ if _anObject_ is an instance of
_mod_ or one of _mod_'s descendents. Of limited use for modules,
but can be used in +case+ statements to classify objects by
class.

Ok, out of the three of us that responded, Mike is the one who knows
what he's talking about most. Listen to him.

Tim
 
J

Joe Van Dyk

case doesn't use =3D=3D you can do this:

a =3D 5

case a
when Fixnum
puts "I'm a fixnum"
else
puts "other"
end

Very nice, thanks! Less code is always better.
 
D

dblack

Hi --

I'll admit I only started learning Ruby 3 days ago, so don't hold it
against me if I misguide you ;), but I believe switch uses '===' to
compare, which I think is a more precise match...

5.class == Fixnum => true
5.class === Fixnum => false

(I've fixed your Fux :)

It's not that it's more precise; it's just different. For classes,
=== is defined so that:

X === x

is true if X is the class of x or one of that class's ancestors. The
idea is to make it easy to do:

case obj
when X ...
when Y ...

But when obj is itself a class, you'll only get a positive if you test
to see whether it's a Class object:

case 5.class
when Class # this will be true


David

--
David A. Black ([email protected])
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! http://www.manning.com/books/black
 
T

Timothy Bennett

Ok, this is off the original track of discussion a bit, but I wanted
to bring this up.

irb(main):007:0> 5 === Fixnum
=> false
irb(main):008:0> Fixnum === 5
=> true

irb(main):001:0> 5.class === Class
=> false
irb(main):002:0> Class === 5.class
=> true

I understand why this is happening (I think). I just think this
needs to be fixed. Or is there a reason why === should not be
commutative?

Tim
 
M

Mike Stok

Ok, this is off the original track of discussion a bit, but I
wanted to bring this up.

irb(main):007:0> 5 === Fixnum
=> false
irb(main):008:0> Fixnum === 5
=> true

irb(main):001:0> 5.class === Class
=> false
irb(main):002:0> Class === 5.class
=> true

I understand why this is happening (I think). I just think this
needs to be fixed. Or is there a reason why === should not be
commutative?

I think of it more as a relationship which has "direction", so in my
view there's nothing to be fixed. In the class comparison it's
testing whether the class of the operand is the same as _or an
ancestor of_ the receiver. So it's not plain same as. (wording taken
from the Pickaxe book)

Mike

--

Mike Stok <[email protected]>
http://www.stok.ca/~mike/

The "`Stok' disclaimers" apply.
 
C

Caleb Clausen

Ok, this is off the original track of discussion a bit, but I wanted
to bring this up.

irb(main):007:0> 5 =3D=3D=3D Fixnum
=3D> false
irb(main):008:0> Fixnum =3D=3D=3D 5
=3D> true

irb(main):001:0> 5.class =3D=3D=3D Class
=3D> false
irb(main):002:0> Class =3D=3D=3D 5.class
=3D> true

I understand why this is happening (I think). I just think this
needs to be fixed. Or is there a reason why =3D=3D=3D should not be
commutative?

For the cases you give, it seems pretty straightforward, but what about thi=
s:

Fixnum=3D=3D=3DClass #false
Class=3D=3D=3DFixnum #true

Should Class be considered a Fixnum just because Fixnum is a Class?
 
T

Timothy Bennett

For the cases you give, it seems pretty straightforward, but what
about this:

Fixnum===Class #false
Class===Fixnum #true

Should Class be considered a Fixnum just because Fixnum is a Class?

Hm, at least that makes sense. However, it's hard for me to think of
=== as having direction (it doesn't look like it has direction, and
therefore it can be difficult to remember which direction it's
supposed to go sometimes).

Though for some reason it's easier for me to accept that (1..5) === 3
gives true while 3 === (1..5) gives false. I'll have to remember it
that way, and later I'll probably wince when I recall that 5 ===
Fixnum #=> false confused me (assuming that I'm able to recall this,
which I probably won't as my memory is pretty bad. So some day in
the future someone will say to me "This used to confuse you!" and
show me this email and I shall suffer from horror and shock at
evidence of my old ignorance.)

And no, that is not an invitation to approach me one day with this
email in hand :)

Tim
 
H

Hal Fulton

Timothy said:
Hm, at least that makes sense. However, it's hard for me to think of
=== as having direction (it doesn't look like it has direction, and
therefore it can be difficult to remember which direction it's supposed
to go sometimes).

I drew some (a little) criticism for spending four pages
in _The Ruby Way_ covering the case statement.

I think it's powerful, and I think it's done the Right Way,
and shouldn't be changed.

But I also think there are some non-obvious quirks (such as
you describe).

It also bears remembering that === is not called on the item
being tested, but on each of the items tested against. So

case x
when a
do_something
end

means

if a === x
do_something
end


HTH,
Hal
 
T

Timothy Bennett

I drew some (a little) criticism for spending four pages
in _The Ruby Way_ covering the case statement.

I think it's powerful, and I think it's done the Right Way,
and shouldn't be changed.

But I also think there are some non-obvious quirks (such as
you describe).

If four pages is what it takes.... I haven't read the Ruby Way yet
(maybe if I had I wouldn't have been confused), but at the moment I
wish that either Why's PG or the Pickaxe covered === a bit better. I
also wish that it looked asymmetrical (maybe ==~ instead of ==,
though that would invite people to think of it in relation to =~,
which probably wouldn't be good either). Anyway, I think I'll be
able to keep its role straight in my head.

Thanks for the help, guys.

Tim
 
D

Dave Burt

Timothy said:
... I also wish that it looked asymmetrical (maybe ==~ instead of ==,
though that would invite people to think of it in relation to =~, which
probably wouldn't be good either). Anyway, I think I'll be able to keep
its role straight in my head.

Actually there is a conceptual relationship between === and =~ - it is a
kind of matching. Regexp's === matches against strings, Range's === matches
things inside its range. As far as case and === is concerned, it helps me to
think of a class as something that matches instances in a similar way.

Cheers,
Dave
 
M

Mike Austin

Timothy said:
Ok, this is off the original track of discussion a bit, but I wanted to
bring this up.

irb(main):007:0> 5 === Fixnum
=> false
irb(main):008:0> Fixnum === 5
=> true

irb(main):001:0> 5.class === Class
=> false
irb(main):002:0> Class === 5.class
=> true

So that was what got me a few weeks ago when using a case statement! I was
like 'what the ?? is happening' It seems the === operator is an good example
of bad overloading - it means something different to each class. Why not let
"abc" === "ABC" while we're at it ;)

Mike
 
P

Pit Capitain

Timothy said:
Hm, at least that makes sense. However, it's hard for me to think of
=== as having direction (it doesn't look like it has direction, and
therefore it can be difficult to remember which direction it's supposed
to go sometimes).

After using it a couple of times, it's not that hard. I'm sure you have
no problems with

5 - 3

;-)

Regards,
Pit
 

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

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,175
Latest member
Vinay Kumar_ Nevatia
Top