13

我必须对 Perl 脚本进行修改,这是我第一次尝试理解 Perl。我看到以下内容:

my %trades;
...
foreach my $row (@$rows) {
  @{$trades{pop @$row}} = @$row;
}

我对此感到困惑,因为似乎我们正在弹出数组中的最后一项@$row并将哈希键设置%trades为弹出的项并将值设置为@$row

这种理解正确吗?

4

2 回答 2

26

要理解那段代码,我们需要清楚三件事:

  • 评估顺序:

    EXPR_A = EXPR_B
    

    先评估EXPR_B再评估EXPR_A

  • 复制语义:

    @new_array = @old_array
    

    @old_array将over的值复制到@new_array

  • 复杂数据结构的解引用:

    @{ $trades{$key} }
    

    访问散列中调用的条目$key%trades并将其视为数组引用。

总之,您的代码等同于:

foreach my $row (@$rows) {
  my @copy = @$row;
  my $key = pop @$row;
  @{ $trades{$key} } = @copy;
}

(同时保留我能看到的所有副作用)

所以例如

$rows = [
  [1, 2, "keyA"],
  [3, 4, "keyB"],
];

会创造

%trades = (
  keyA => [1, 2, "keyA"],
  keyB => [3, 4, "keyB"],
);
$rows = [
  [1, 2],
  [3, 4],
];

写那行的人对评估顺序有非常精确的了解,并且喜欢折磨维护程序员。

于 2013-06-07T16:48:50.503 回答
3

循环相当于

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

除了这种方式@$rows保持不变。IMO应该这样写。

于 2013-06-07T18:58:56.787 回答