For Float#class why is '===' different from '=='

# Sorry, very newbie question ...

C:/> ruby -v
ruby 1.8.2 (2004-12-25) [i386-mswin32]

C:/> irb
irb(main):001:0> a = 3.2
=> 3.2
irb(main):002:0> puts "match" if a.class==Float
match
=> nil
irb(main):003:0> puts "match" if a.class===Float
=> nil
irb(main):004:0>

Why does '==' match, and '===' does not. I am trying to use a case
statement on the class and it doesn't work because '===' is not giving
the newbie expected result.

Please don't hurt me. Thanks for your patience! - RichB

No one wants to hurt you my friend, in fact ruby has anticipated your need:

a = 2.3

case a
when Float
...
end

p Float === 1.2

···

On Aug 8, 2006, at 8:30 PM, richB wrote:

# Sorry, very newbie question ...

C:/> ruby -v
ruby 1.8.2 (2004-12-25) [i386-mswin32]

C:/> irb
irb(main):001:0> a = 3.2
=> 3.2
irb(main):002:0> puts "match" if a.class==Float
match
=> nil
irb(main):003:0> puts "match" if a.class===Float
=> nil
irb(main):004:0>

Why does '==' match, and '===' does not. I am trying to use a case
statement on the class and it doesn't work because '===' is not giving
the newbie expected result.

Please don't hurt me. Thanks for your patience! - RichB

The triple equals is a length of velvet rope, checking values much like
the double equals. The triple equals is the relationship operator for
Date.For example:

irb(main):001:0> year = 2005
=> 2005
irb(main):002:0> puts "included" if 2000..2006 === year
included
=> nil

···

--
Posted via http://www.ruby-forum.com/.

richB <richard_a_brunner <at> yahoo.com> writes:

Why does '==' match, and '===' does not. I am trying to use a case
statement on the class and it doesn't work because '===' is not giving
the newbie expected result.

As others have said, === is a function call

case a
when Float # Float === a
when 2005 # 2005 === a

2005 is a FixNum, and FixNum implements === the same as ==
Float is a Class (as you'll see if you type Float.class), and Class implements
=== basically like this as far as I can tell:

class Class
  def ===(other)
    other.kind_of? self
  end
end

So, the reason you're getting the result you're getting is because a === b
doesn't necessarily mean b === a - it depends on the classes of a and b

Gareth

Zikiss Chan wrote:

irb(main):001:0> year = 2005
=> 2005
irb(main):002:0> puts "included" if 2000..2006 === year
included
=> nil

Here's the key:
irb(main):006:0> puts "too bad" if 2000..2004 == year
too bad
=> nil
irb(main):007:0> puts "not equal to the range" if 2000..2004 === year
not equal to the range
=> nil

···

--
Posted via http://www.ruby-forum.com/\.

I appreciate the responses. I'm still puzzled. It seems that "case a"
is different from "case a.class" and that the comparison being done by
"===" in when is influenced by the type/class of the when operand.

I guess I wasn't expecting this. I am still trying to iron out my
conceptual understanding. Is it that "case a" is asking about the
object a, whereas
"case a.class" is asking about the object/attribute a.class. Clearly a
is Float but a.class is something else that evaluates to Float?

irb(main):001:0> a=2.3
=> 2.3
irb(main):002:0> case a.class
irb(main):003:1> when Float then puts "match"
irb(main):004:1> end
=> nil

irb(main):005:0> a=2.3
=> 2.3
irb(main):006:0> case a
irb(main):007:1> when Float then puts "match"
irb(main):008:1> end
match
=> nil

irb(main):009:0> a.class
=> Float

irb(main):010:0> case a
irb(main):011:1> when 2.3 then puts "match"
irb(main):012:1> end
match
=> nil

Thanks!

richB wrote:

I appreciate the responses. I'm still puzzled. It seems that "case a"
is different from "case a.class" and that the comparison being done by
"===" in when is influenced by the type/class of the when operand.

I guess I wasn't expecting this. I am still trying to iron out my
conceptual understanding. Is it that "case a" is asking about the
object a, whereas
"case a.class" is asking about the object/attribute a.class. Clearly a
is Float but a.class is something else that evaluates to Float?

What I mean to say is "a.class" is something that indicates "a" is a
Float, but "a.class" is not itself a Float value.

richB wrote:

I appreciate the responses. I'm still puzzled. It seems that "case a"
is different from "case a.class" and that the comparison being done by
"===" in when is influenced by the type/class of the when operand.

Like most operators, === is just a method call. The following are equivalent:
   case a
   when b
and
   if b === a

Therefore the behavior of === depends on b. If b is a Class (e.g. Float), it's equivalent to a.is_a?(b). If b is a Float (e.g. 2.3), it's equivalent to b == a.

I usually view the === operator as the inclusion operator:
   b === a -> does b include a?

which brings me to... would there be any nasty side-effects to this?
   class Object
     def ===(other)
       if respond_to?(:include)
         self == other or include?(other)
       else
         self == other
       end
     end
   end

Daniel

"richB" <richard_a_brunner@yahoo.com> writes:

I appreciate the responses. I'm still puzzled. It seems that "case a"
is different from "case a.class" and that the comparison being done by
"===" in when is influenced by the type/class of the when operand.

Yes. The best way I have of mentally modelling === is this:

lhs === rhs means "Does rhs match lhs?", where the definition of
what matches depends of course on the nature of lhs.

When lhs is a class object, it makes sense to say that 'match' means
the same as 'is_a?'. When lhs is a range, it makes sense to say that
'match' means the same as 'includes?'. When lhs is a Regexp, 'match'
already has a useful meaning.

richB wrote:

richB wrote:

I appreciate the responses. I'm still puzzled. It seems that "case a"
is different from "case a.class" and that the comparison being done by
"===" in when is influenced by the type/class of the when operand.

I guess I wasn't expecting this. I am still trying to iron out my
conceptual understanding. Is it that "case a" is asking about the
object a, whereas
"case a.class" is asking about the object/attribute a.class. Clearly a
is Float but a.class is something else that evaluates to Float?

What I mean to say is "a.class" is something that indicates "a" is a
Float, but "a.class" is not itself a Float value.

Right. a.class is Float which is a constant. Float.class is Class.

The #=== operator which I call the 'sorta' operator usually indicates
some kind of a, er, kind-of, range or inclusion relationship. For
example with Ranges, #=== tests whether a value is within the range.

The most prominent use of #=== is the case expression which uses
it to compare for equality--or inclusion--instead of the more
traditional #==. This enables interesting usage of case.

A particular implementation, Class#===, is of interest to you:

a.class == Float # true
Float === a # true

ri Object#===

···

--
Posted via http://www.ruby-forum.com/\.