Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Journal of jjore (6662)

Friday June 22, 2007
02:01 PM

UNIVERSAL::isa( ..., 'HASH') , please die harder.

[ #33580 ]

I just realized another reason why UNIVERSAL::isa( $obj, 'HASH' ) breaks stuff. Assume first that $obj is overloaded and is just a proxy for something real. That real thing might be an array reference or a hash reference or whatever. It might not even be a reference on the other end. It's just a proxy. It's Devel::Spy, honestly.

So tye told me to make my proxy be ISA HASH so UNIVERSAL::isa( $obj, 'HASH' ) would DRT. It took me a few months to realize, (yes, I know, dumb of me) that I only want *some* objects to be ISA HASH. Only the ones that really do have the ability to be dereferenced as a hash.

my %subclasses;
if ( eval { 1 + %$thing_to_wrap } ) {
    $subclasses{HASH} = 1;
}
# repeat for array, scalar, etc.
 
$subclass = join '_', sort keys %subclasses;
 
bless $obj, "Devel::Spy::$subclass";
 
package Devel::Spy::HASH;
@ISA = 'HASH';
 
package Devel::Spy::ARRAY_HASH;
@ISA = qw( ARRAY HASH );
 
... # etc

That covers everything at object construction time. Now what if the thing I've just wrapped gains or loses a dereferencing ability? Argh! Perl's dynamic so this is something that's allowed to happen.

Again, I end up coming back a conclusion that using UNIVERSAL::isa( $obj, 'HASH' ) in user code is wrong. It breaks stuff that perl allows.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • I went through this in this perlmonks thread [perlmonks.org] with tye [perlmonks.org] and chromatic [perlmonks.org], and I'm still not sure if there is any absolute best answer. Even with the eval method, you have to watch out for pseudohashes [perlmonks.org] (in at least some version(s) of perl).
    • Actually, using your '1 + %$href' instead of my '%$href' gets around the pseudohash problem I had, but if an array reference CAN be a valid psuedohash, dereferencing it as a hash reference is valid:

      use strict;
      use warnings;

      my $href = [ { a => 0, b => 1 }, 3, 4 ];

      if ( eval { 1 + %$href } ) {
          print "href is a hash ref\n";
      }

      ######################
      Pseudo-hashes are deprecated at tst.pl line 8.
      Argument "2/8" isn't numeric in addition (+) at tst.pl line 8.
      href is a hash ref