How to dereference hash references

2020-05-03 10:29发布

问题:

UPDATE: Everything I know about referencing/dereferencing came from here: http://www.thegeekstuff.com/2010/06/perl-array-reference-examples/

I'm working with a library that (from the library documentation):

Returns a reference to an array of hash references

This conceptually makes sense to me (i'm not new to programming) but doesn't make sense functionally (i'm, apparently, very new to perl).

Here's some code:

my $Obj  = QA::STK::ModuleImUsing->new(arguments, to, new);
$Obj->createClient();
$Obj->sync( ['/tmp/files/...']);
my $result = $Obj->method_in_question(['/tmp/files/ff-latest.xml']);

So far so good. $result now holds the reference to an array.

So when I do this:

print "Result: @{ $result} \n";

I get:

Result: HASH(0x20d95b0)

Lovely! But I still need to dereference the hash. However, here's where things get weird (or maybe they've already gotten weird?).

my $hash_ref = @{ $result};
print Dump($hash_ref));

I get this:

$VAR1 = 1;

Which...isn't what I was expecting at all.

Are my expectations wrong or am I dereferencing things in the wrong way?

回答1:

If @$result is an array then your LHS must be a list. Otherwise $hashref will be assigned the array size.

my ($hash_ref) = @{ $result};
print Dump($hash_ref));


回答2:

  • We have a %hash.
  • To this, we have a hash reference $hashref = \%hash
  • This hashref is inside an array @array = ($hashref)
  • We get an array reference: $arrayref = \@array

This is our result: $result = $arrayref. Not let's work backwards:

  • @result_array = @$result
  • $result_hashref = $result_array[0] or combined: $result_hashref = $result->[0]
  • %result_hash = %$result_hashref or combined: %result_hash = %{ $result->[0] } (note that these make a copy)
  • To get an element in the result hash, we can do
    • $result_hash{$key}
    • $result_hashref->{$key}
    • $result->[0]{$key}

Note that $scalar = @{ $arrayref } does not work as you expect, because an array (which @{ … } is) returns the length of the array in scalar context. To force list context in an assignment, put the left hand side into parens: (…) = here_is_list_context (where is a list of zero or more lvalues).



回答3:

my $hash_ref = @{$result};

is the same as

my @array = @{$result};
my $hash_ref = @array;

This forces the array to be evaluated in scalar context by the assignment operator, which causes it to evaluate as the number of items in the array, or 1.