develooper Front page | perl.perl5.porters | Postings from March 2007

Re: Object Identification Cold War and the return of autobox.pm (wasRe:UNIVERSAL::ref might make ref( $mocked_obj ) sane)

Thread Previous | Thread Next
From:
Adam Kennedy
Date:
March 1, 2007 16:38
Subject:
Re: Object Identification Cold War and the return of autobox.pm (wasRe:UNIVERSAL::ref might make ref( $mocked_obj ) sane)
Message ID:
20070302003843.21289.qmail@lists.develooper.com
Michael G Schwern wrote:
> Yuval Kogman wrote:
>>> Likewise with ref in boolean context, I almost never want the object
>>> to be able to lie to me.
>> But if it has to work hard to lie, then does it matter?
> 
> Yeah, I'm with Yuval here.  There seem to be a cold war going on here wrt
> identifying an object.
> 
> In the beginning we used UNIVERSAL::isa() and UNIVERSAL::can().  And it
> could identify the nature of any scalar, blessed or not.  Reference or not.
>  And it was good.
> 
> And then someone got clever and overrode isa() and can().  And there was
> much wailing and nashing of teeth and slaughtering of lambs.  Now we're
> supposed to use C<< eval { $obj->isa($class) } >> and for a while balance
> was restored.

Well, except you aren't supposed to do that, because if ->isa can be 
overloaded, it can also die or throw an exception. So eval { 
$obj->isa($class) } falsely ignores errors.

> And then someone defined a $SIG{__DIE__} so now its C<<{ local
> $SIG{__DIE__};  eval { $obj->isa($class) } }>> or you must depend on having
> a 3rd party module written in XS, Scalar::Util, available and compiled and
> do C<<use Scalar::Util qw(blessed);  blessed $obj && $obj->isa($class) >>.

This just compounds the above-mentioned mistake.

> And then someone got really clever and blessed their object into class "0".
>  Now we must do C<<use Scalar::Util qw(blessed);  defined blessed $obj &&
> $obj->isa($class) >>.  Or if you can't rely on Scalar::Util:  C<< local
> $SIG{__DIE__};  eval { $obj->isa($class) } >>.

And this compounds it further.

> But what if isa() is broken or has side effects, hmm?  And what if its lying
> to me and I *really* want to know what methods are *really* available and
> not autoloaded?  And what if someone got even more clever and blessed into
> class ""...
> 
> ARGHAGHAGHGGGGHHH!
> 
> IT SHOULD NOT BE THIS COMPLICATED TO IDENTIFY THE HERITAGE OF AN OBJECT!

use Params::Util '_INSTANCE';

if ( _INSTANCE($obj, 'Whatever') ) {

}

> The best practice should be straightforward:  Ask the object.  If it wants
> to lie to you and override isa() or use class "0" (and yes, there really is
> no other reason to use such a class name but to lie) then damned well let
> it.  We call this "encapsulation" and it is good.

Yep, I was pissed off too, so the above tries to compensate for the 
problems and re-encapsulate what you originally meant by UNIVERSAL::isa().

> 99.999% of the time you do not want to really know how something is
> implemented, you want to remain ignorant.

I concur, which is what really pisses me off them 
IO::String->new(\$string)->isa('IO::Handle') returns false, because the 
author believes in duck typing over actually having isa describe the 
interfaces.

   It is detrimental for your
> shopping cart code to pierce the facade surrounding the objects it is using.
>  The remaining 0.001% of the time you're writing something like Data::Dumper
> or a serialization module and fine, employ all the magic you like, but don't
> try to apply the needs of a module like Data::Dumper to Joe Business
> Programmer!  If I caught someone blessing into class "0" at my work he'd
> have to give such a damned good reason that I wouldn't use his eye sockets
> for USB ports.
> 
> All the trouble here seems to stem from the fact that its so damned hard to
> reliably determine what is and is not an object.  And the only reason we
> care about that is so we can call isa() on it.  The proper way to identify
> the nature of an object is C<< $obj->isa($class) >>.  The proper way to
> identify whether a class has a method is C<< $obj->can($method) >>.  Done.
> All the other junk we do these days is determining if its blessed so there's
> not an error when we try to call a method on it.
> 
> Solution... make everything an object.  Or at least everything callable with
> methods.  Or for bloody screaming hell at least the UNIVERSAL ones!  This is
> called "autoboxing" and there's already a module out there to do it.
> http://search.cpan.org/dist/autobox.  In one fell swoop all this nonsense
> goes away.  It doesn't even require a core patch anymore.
> 
> $ perl -Mautobox -wle 'print []->isa("ARRAY");'
> 1
> 
> autobox.pm was proposed as a core module many moons ago but it was rejected
> as not being necessary.  As its a central tenet of any decent OO language
> that everything should be (or at least act like) an object I was very
> dismayed at that.  Well, here's your use case.
> 
> Please reconsider autobox.

heh :)

Adam K

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About