Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does it mean when a Perl method returns a "hashref"?

Tags:

perl

I'm trying to decrypt a Perl code which I'm not familiar with, somehow related to HashRef. I'm using Amazon::S3, but my question is a general Perl question. See the code below:

use Amazon::S3;
my $s3 = Amazon::S3->new( ... );
my $response = $s3->buckets;

Documentation (here) sais, about s3->buckets:

Returns undef on error, else HASHREF of results

The following line is working for me, but I don't understand why:

for $b in ( @ { $response->{buckets} } ) {
    print "bucket: " . $b->bucket . "\n";
}

I'm Puzzled by each operator on the first line.

What type exactly are $response, $respone->{bucket}. Looks like the expression within the for is an array, but I don't understand this syntax: @{ ... }?

like image 372
Uri Avatar asked May 15 '10 15:05

Uri


2 Answers

Let's go through it piece-by-piece.

$s3 is your S3 object. $s3->buckets calls the buckets method on that object, and we store the results in $response. As the docs say, the results are a hash reference; a reference is a scalar that points to another value. If you're familiar with pointers, the idea is the same.

If we had a plain hash %response, we could get at the buckets key in the hash by saying $response{buckets}. Since we have a hash reference, we have to use the dereference operator (->) to get at the key, so that becomes $response->{buckets}.

But we're not done yet. $response->{buckets} is itself a reference, in this case an array reference. Here we see another form of dereferencing. We could, if we wanted to get at just one item in the referenced array, say $response->{buckets}[0], for example. But we want the whole list, so we use the @ operator to dereference the entire array. Since our array reference is contained in a complex structure, we use curlies to contain the expression that has the reference. So @{ $response->{buckets} } gets us the array.

That's doing a whole lot in a single statement.

For more on references, which can be one of the trickiest subjects to learn in Perl, see the following:

  • perlreftut - Perl reference tutorial
  • perldsc - Perl data structures cookbook
  • perllol - All about arrays of arrays
  • perlref - The main Perl references documentation
like image 154
friedo Avatar answered Nov 12 '22 03:11

friedo


Welcome to the world of Perl references! You're going to find the reference tutorial very handy.

The syntax @{...} takes a scalar value and tries to de-reference it into an array. There's also %{...}, which tries to de-reference into a hash. The curlies are optional, so you can also write @$reference or %$reference to get the same effect. Some people find them visually useful when the reference is inside a hash or an array, as is the case here.

To help you understand the data structure a bit more, try using something like Data::Dumper.

use Data::Dumper;
print Dumper $response;
print Dumper $response->{buckets};
# The docs say that buckets is a hashref.  It also happens that
# you can coerce a hash into an array.  Let's treat it as a hash
# and see what's inside it, manually.  The Dumper call above should
# have already provided the structure to you, though.
foreach my $k (keys %{$response->{buckets}}) {
    print "$k => " . Dumper $response->{buckets}->{$k}
}
like image 27
Charles Avatar answered Nov 12 '22 02:11

Charles