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. 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) >>. 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) } >>. 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! 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. 99.999% of the time you do not want to really know how something is implemented, you want to remain ignorant. 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.