I have to make modifications to a Perl script, and this is my first attempt at understanding Perl. I see the following:
my %trades;
...
foreach my $row (@$rows) {
@{$trades{pop @$row}} = @$row;
}
I am confused by this because it appears that we are popping off the last item in the array @$row
and setting the hash key of %trades
to be the item that was popped off and setting the value to be @$row
.
Is this understanding correct?
To understand that piece of code, we need to be clear of three things:
Evaluation order:
EXPR_A = EXPR_B
evaluates EXPR_B
before evaluating EXPR_A
.
Copying semantics:
@new_array = @old_array
copies the values of @old_array
over to @new_array
.
Dereferencing of complex data structures:
@{ $trades{$key} }
accesses the entry called $key
in the %trades
hash, and treats it as an array reference.
Together, your code is equivalent to this:
foreach my $row (@$rows) {
my @copy = @$row;
my $key = pop @$row;
@{ $trades{$key} } = @copy;
}
(while preserving all side effects I can see)
So for example
$rows = [
[1, 2, "keyA"],
[3, 4, "keyB"],
];
would create
%trades = (
keyA => [1, 2, "keyA"],
keyB => [3, 4, "keyB"],
);
$rows = [
[1, 2],
[3, 4],
];
Whoever wrote that line had very precise knowledge about evaluation order and loves to torture maintenance programmers.
The loop is equivalent to
my %trades = map { $_->[-1] => [ @$_ ] } @$rows
except that this way @$rows
remains unmodified. IMO it should be written that way.
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