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