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

jjore on 2007-06-22T19:01:01

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.


Is it really a hash?

runrig on 2007-06-23T16:26:17

I went through this in this perlmonks thread with tye and chromatic, 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 (in at least some version(s) of perl).

Re:Is it really a hash?

runrig on 2007-06-23T16:54:35

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