Search code examples
perlhashreferencesubroutine

How do I dereference this hash in perl?


#!/usr/bin/perl
use Data::Dumper;

sub giveMeARef {
    my %hash = %{$_[0]};

    print "arg: ", Dumper($_[0]);
    print "deref: ", Dumper(%hash);
}

my %hash = ( "a" => (1,2,3), "b" => (3,4,5));

giveMeARef(\%hash);

This produces the following output:

arg: $VAR1 = {
          '2' => 3,
          '4' => 5,
          'a' => 1,
          'b' => 3
        };
deref: $VAR1 = 'b';
$VAR2 = 3;
$VAR3 = '2';
$VAR4 = 3;
$VAR5 = 'a';
$VAR6 = 1;
$VAR7 = '4';
$VAR8 = 5;

I tried to follow the examples in How do I dereference a Perl hash reference that's been passed to a subroutine?

But I believe because my hash is more complicated, it isn't working out for me. How do I get back to the original structure I passed in?


Solution

  • As I mentioned in my comment, you're flattening a list when you create %hash. The fat comma (=>) is a synonym for the comma that causes barewords on the left to be interpreted as strings, but it doesn't matter in this case because you've already got a string on the left. In effect, your hash assignment really looks like this:

    my %hash = ("a", 1, 2, 3, "b", 3, 4, 5);
    

    It looks like you were trying to assign arrays to a and b, but in Perl, hash values are always scalars, so you need to use references to anonymous arrays instead:

    my %hash = (a => [1, 2, 3], b => [3, 4, 5]);
    

    It's also worth noting that your subroutine is making a shallow copy of the hash reference you pass in, which may have unintended/unforeseen consequences. Consider the following:

    use Data::Dump;
    
    sub giveMeARef {
        my %hash = %{$_[0]};
        pop(@{$hash{a}});
    }
    
    my %hash = (a => [1, 2, 3], b => [3, 4, 5]);
    
    dd(\%hash);
    giveMeARef(\%hash);
    dd(\%hash);
    

    Which outputs:

    { a => [1, 2, 3], b => [3, 4, 5] }
    { a => [1, 2], b => [3, 4, 5] }