[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Module#=== vs Object#is_a?

Peter Fitzgibbons

2/7/2009 12:15:00 PM

[Note: parts of this message were removed to make it a legal post.]

HI All,

Could somone explain the subtle difference between Module#=== and
Object#is_a?

I found a usage of === to test if an argument is Regexp or not... just want
to know the restrictions.
The code is beautiful...

if Regexp === regexp_or_string


Peter Fitzgibbons
(847) 687-7646
Email: peter.fitzgibbons@gmail.com
IM GTalk: peter.fitzgibbons
IM Yahoo: pjfitzgibbons
IM MSN: pjfitzgibbons@hotmail.com
IM AOL: peter.fitzgibbons@gmail.com

13 Answers

Stefano Crocco

2/7/2009 12:26:00 PM

0

Alle Saturday 07 February 2009, Peter Fitzgibbons ha scritto:
> HI All,
>
> Could somone explain the subtle difference between Module#=== and
> Object#is_a?
>
> I found a usage of === to test if an argument is Regexp or not... just want
> to know the restrictions.
> The code is beautiful...
>
> if Regexp === regexp_or_string
>

Looking at the ri documentation for the two methods, I'd say they do exactly
the same thing.

Stefano

ThoML

2/7/2009 12:44:00 PM

0

> Could somone explain the subtle difference between Module#=== and
> Object#is_a?

=== is used in case statements and can be overridden in subclasses.

David A. Black

2/7/2009 12:49:00 PM

0

On Sat, 7 Feb 2009, Peter Fitzgibbons wrote:

> HI All,
>
> Could somone explain the subtle difference between Module#=== and
> Object#is_a?
>
> I found a usage of === to test if an argument is Regexp or not... just want
> to know the restrictions.
> The code is beautiful...
>
> if Regexp === regexp_or_string

They're the same, in essence. === is bound to the C method rb_mod_eqq,
which looks like this:

static VALUE
rb_mod_eqq(VALUE mod, VALUE arg)
{
return rb_obj_is_kind_of(arg, mod);
}

=== is usually a light wrapper around something, mainly so that the
case construct can use it implicitly. (It always looks a bit odd to me
used explicitly, since it usually has semantics that don't relate to
anything that equal signs normally signify.)


David

--
David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.r...
Coming in 2009: The Well-Grounded Rubyist (http://manning....)

http://www.wis... => Independent, social wishlist management!

Igor Pirnovar

2/7/2009 10:00:00 PM

0

Peter Fitzgibbons wrote:
> HI All,
>
> Could somone explain the subtle difference between Module#=== and
> Object#is_a?
>
> I found a usage of === to test if an argument is Regexp or not... just
> want
> to know the restrictions.
> The code is beautiful...
>
> if Regexp === regexp_or_string

The Class class defines === operator in such a way that it can be used
in place of is_a.
+---------------------------------------------+
| x = 1 |
| Numeric === x # => true: x is_a Numeric |
+---------------------------------------------+
This is exactly the same use as your:
+---------------------------------------------+
| if Regexp === regexp_or_string |
+---------------------------------------------+

All the technical details about Ruby implementation of === and is_a are
pretty much irrelevant. What is important is the meaning of the test we
perform with these and similar operators. As others already pointed out
"===" and "is_a" are used to obtain exactly the same info about
instances or classes. You can find the best explanation about this in
the defacto Ruby bible called "The Ruby Programming Language" by D.
Flanagan and Y. Matsumoto, in chapter "8.1 Types, Clases and Modules".
Let me copy it out here:

The most commonly used reflective methods are those for determining the
type of an object - what class it is an instance of, and what methods it
responds to. ... To review:

o.class
Returns the class of an object o.
c.superclass
Returns the superclass of a class c.
o.instance_of? c
Determines whether the object o.class == c.
o.is_a? c
Determines whether o is an instance of c, or of any of its
subclasses. If c is a module, this method tests wether o.class (or any
of its ancestors) includes the module.
o.kind_of? c
kind_of? is a synonym for is_a?
c === o
For any class or module c, determines if o.is_a?(c)
o.responds_to? name
Determines whether the object o has a public or protected method
with the specified name. Pass true as the second argument to check
private methods as well. i.e: o.responds_to?("name", true)
--
Posted via http://www.ruby-....

Peter Fitzgibbons

2/7/2009 10:51:00 PM

0

[Note: parts of this message were removed to make it a legal post.]

I love it!

Thank you all for the discourse.

I take Igor's reference to the Ruby bible as the most authoritative
explanation, which directly indicates that these two are *intended* to be
equivalent constructs.

What I like about === most is that it was very elegant looking AND made me
stop to go find out exactly what was going on. Metaprogramming beauty. I
suppose that goes against the grain of some who wish for the code to tell
you clearly what is going on without reference... but how would you know
what <=> or ||= are without reference?

So, I'll be using === instead of is_a?

Thanks all!

Peter Fitzgibbons
(847) 687-7646
Email: peter.fitzgibbons@gmail.com
IM GTalk: peter.fitzgibbons
IM Yahoo: pjfitzgibbons
IM MSN: pjfitzgibbons@hotmail.com
IM AOL: peter.fitzgibbons@gmail.com

David A. Black

2/7/2009 11:27:00 PM

0

Hi --

On Sun, 8 Feb 2009, Peter Fitzgibbons wrote:

> I love it!
>
> Thank you all for the discourse.
>
> I take Igor's reference to the Ruby bible as the most authoritative
> explanation, which directly indicates that these two are *intended* to be
> equivalent constructs.

Yes, it wasn't an accident :-) It's in keeping with the purpose of
===. Basically, === exists so that it can be overridden in classes
(including, but not limited to, Module), and will then exhibit
appropriate behavior for different classes, in case statements.

Thus, for example, Regexp#=== does a match test:

case "abc"
when /abc/ ... # /abc/ === "abc"
end

> What I like about === most is that it was very elegant looking AND made me
> stop to go find out exactly what was going on. Metaprogramming beauty. I
> suppose that goes against the grain of some who wish for the code to tell
> you clearly what is going on without reference... but how would you know
> what <=> or ||= are without reference?

It's great to learn what it all means, but I wouldn't necessarily use
some of these intentionally generic methods explicitly. For example, I
would rather do this:

a > b

than this:

(a <=> b) == 1

though of course I want to know what <=> and how to implement my own
<=> methods when necessary. The same holds (even more so in a way,
since <=> at least has consistent semantics) for ===, which is
designed to be overridden and therefore fluid as to its semantics and
meaning.

=== is very cool because it lets you define your own case statements
and have them work based on a method, without your having to call the
method explicitly. And of course if you make up your own meanings for
===, they're not going to be as obvious as the ones for the built-in
classes (which are few enough that it's not hard to learn them, even
though they usually have more expressive alternatives). For example,
it's better to write:

if car.make == make

than

if make === car

which is not indecipherable but which definitely does need to be
deciphered and which even then has a peculiar backwards ring to
it. You might, however, want make objects to be engineered so that
they can case-compare themselves with a car:

case car
when Ford ...

etc., but the explicit === can be a bit too much of a "secret
handshake".


David

--
David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.r...
Coming in 2009: The Well-Grounded Rubyist (http://manning....)

http://www.wis... => Independent, social wishlist management!

Robert Dober

2/8/2009 1:22:00 PM

0

On Sun, Feb 8, 2009 at 12:27 AM, David A. Black <dblack@rubypal.com> wrote:
>
> if car.make == make
>
> than
>
> if make === car
Although I am a big fan with using #=== (for fingerlazyness) I have to
agree, after some months of thinking and reading it is probably a bad
idea to use it too much.

I am still not sure for some special cases as e.g.
instance_of_Class === object
or
instance_of_Regex === string
these idioms have some good points too e.g. auto-documenting case
behavior and forcing nubies to learn about #===.

However I really do have a strong opinion ( very loosely hold of course! ) about
make === car
and
car.make == make

David A. Black

2/8/2009 1:45:00 PM

0

Hi --

On Sun, 8 Feb 2009, Robert Dober wrote:

> On Sun, Feb 8, 2009 at 12:27 AM, David A. Black <dblack@rubypal.com> wrote:
>>
>> if car.make == make
>>
>> than
>>
>> if make === car
> Although I am a big fan with using #=== (for fingerlazyness) I have to
> agree, after some months of thinking and reading it is probably a bad
> idea to use it too much.
>
> I am still not sure for some special cases as e.g.
> instance_of_Class === object
> or
> instance_of_Regex === string
> these idioms have some good points too e.g. auto-documenting case
> behavior and forcing nubies to learn about #===.

I don't think it's the right approach to learning, though. I'd rather
see the best possible code, and let people learn from that. No one is
going to really learn about #=== (the fact that it's the case equality
operator, etc.) just by seeing examples of its explicit use.

> However I really do have a strong opinion ( very loosely hold of course! ) about
> make === car
> and
> car.make == make
> .
>
> I would think that if one accepted the first idiom in a project it
> really should convey a very, very strong message, something so
> intrinsic to the problem space that a special idiom is justified.
> In the general case I agree with David though.

I'm not sure you need a "though"; that's essentially the point I was
making :-)


David

--
David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.r...
Coming in 2009: The Well-Grounded Rubyist (http://manning....)

http://www.wis... => Independent, social wishlist management!

Robert Dober

2/8/2009 5:38:00 PM

0

On Sun, Feb 8, 2009 at 2:44 PM, David A. Black <dblack@rubypal.com> wrote:

>
> I'm not sure you need a "though"; that's essentially the point I was
> making :-)
Actually the 'though' was here because we do not agree on the special
usecase for #=== I am quite fond of, and I know that. But that was
quite cryptic for the rest of the world, sorry.

BTW it would help me a lot to understand better why my approach of
using #=== on well defined classes, Class and Regexp that is, does not
help to learn.
This is not about bad code or good code, because I will just not agree that
/===/ === "==="
is bad code ;). [ In my eyes this is probably the most beautiful LOC I
have *ever* written, LOL]

My question would go to the teacher as follows:
Would students not be curious about seeing an unfamiliar idiom? Is
that not often the motivation of posting questions on this list and
sometimes having quite interesting threads.
Funily I try to prove my assumption with this thread, sort of :).
If you feel this is too OT, never mind.

Thanx
Robert
--
It is change, continuing change, inevitable change, that is the
dominant factor in society today. No sensible decision can be made any
longer without taking into account not only the world as it is, but
the world as it will be ... ~ Isaac Asimov

David A. Black

2/8/2009 6:01:00 PM

0

Hi --

On Mon, 9 Feb 2009, Robert Dober wrote:

> On Sun, Feb 8, 2009 at 2:44 PM, David A. Black <dblack@rubypal.com> wrote:
>
>>
>> I'm not sure you need a "though"; that's essentially the point I was
>> making :-)
> Actually the 'though' was here because we do not agree on the special
> usecase for #=== I am quite fond of, and I know that. But that was
> quite cryptic for the rest of the world, sorry.
>
> BTW it would help me a lot to understand better why my approach of
> using #=== on well defined classes, Class and Regexp that is, does not
> help to learn.
> This is not about bad code or good code, because I will just not agree that
> /===/ === "==="
> is bad code ;). [ In my eyes this is probably the most beautiful LOC I
> have *ever* written, LOL]
>
> My question would go to the teacher as follows:
> Would students not be curious about seeing an unfamiliar idiom? Is
> that not often the motivation of posting questions on this list and
> sometimes having quite interesting threads.
> Funily I try to prove my assumption with this thread, sort of :).
> If you feel this is too OT, never mind.

I'm not making a pronouncement that no one should ever see an
unfamiliar idiom in Ruby. That wouldn't make sense, since we're not
born knowing Ruby :-)

But I don't think that Ruby practitioners should decide which idioms
to use based on choosing the one that newcomers are least likely to be
able to understand. The process of people seeing code they don't
understand and asking questions about it is not endangered. It will
keep happening, and it's not really micro-manageable anyway; I don't
think one can plant a particular idiom somewhere with any knowledge
that a nuby is going to spot exactly that usage and wonder about it.


David

--
David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.r...
Coming in 2009: The Well-Grounded Rubyist (http://manning....)

http://www.wis... => Independent, social wishlist management!