Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unusual Perl Syntax

Tags:

perl

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?

like image 567
czchlong Avatar asked Jun 07 '13 16:06

czchlong


2 Answers

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.

like image 130
amon Avatar answered Nov 14 '22 18:11

amon


The loop is equivalent to

my %trades = map { $_->[-1] => [ @$_ ] } @$rows

except that this way @$rows remains unmodified. IMO it should be written that way.

like image 23
Borodin Avatar answered Nov 14 '22 18:11

Borodin