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
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
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
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
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.
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:
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.
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
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.