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: @{ ... }
?
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:
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}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With