perlcpantie

Hashes as Keys in Perl


I am working on a requirement in which keys of hash are hash. I came across the cpan modue Tie::RefHash which can do the job, but somehow it is not working for nested hashes even though I am using Tie::RefHash::Nestable.

my %hash_arg = ();
tie %hash_arg, 'Tie::RefHash::Nestable';
my $hash = { 'mnp' => 1 };
%hash_arg = (
    'pqr' => {
        'a;'  => 1,
        'i'   => 1,
        'mn'  => 1,
        'c'   => 1,
        $hash => 1
    }
);

Hash %hash_arg has a key pqr whose value is a reference to a hash, which has a further hash as a key. When I loop over keys of pqr and try to use the ref function to figure out the hash, it doesn't work.


Solution

  • The reason your code isn't working is that Tie::RefHash works, obviously, through Perl's tie mechanism. That means it does its magic through tie's operations like STORE, FETCH, FIRSTKEY, NEXTKEY etc.

    Your initialisation statement where you set up %hash_arg bypasses all of that, by making the compiler construct a hash which is assigned directly instead of through the tie mechanism

    If you rewrite your code so that the key that is a hash reference is applied at run time then it all works fine

    Take a look at this rewrite of your program. You can see from the dump that the inner hash has all four string keys, a string key HASH(0xd4c2f8) that the compiler assigned, and a proper hash reference key that appears as HASH

    use strict;
    use warnings 'all';
    use v5.10;
    
    use Tie::RefHash;
    use Data::Dump;
    
    tie my %hash_arg, 'Tie::RefHash::Nestable';
    
    my $hash = { 'mnp' => 1 };
    
    %hash_arg = (
        pqr => {
            'a;'  => 1,
            i     => 1,
            mn    => 1,
            c     => 1,
            $hash => 1,
        },
    );
    
    $hash_arg{pqr}{$hash} = 1;
    
    for my $key ( keys %{ $hash_arg{pqr} } ) {
        dd (ref $key or $key);
    }
    

    output

    "HASH"
    "mn"
    "c"
    "i"
    "HASH(0xd4c2f8)"
    "a;"