perl列表哈希引用的上下文

时间:2010-12-16 21:58:05

标签: perl perl-hash

为什么这样做?这是第2行

DB<1> $a = {'a'=>1}; $b = {'a'=>2, 'b'=>0};
DB<2> $c = ($a, $b);
DB<3> print $c;
  HASH(0x8743e68)
DB<4> print $c->{a},$c->{b};
  20

我理解如果我小心地使用%$ a和%$ b perl会知道我的意思,但是在列表中只有裸露的参考,为什么会有效?

或许它看起来像是有效的,我真的做了别的什么?

1 个答案:

答案 0 :(得分:13)

中没有列表上下文
$c = ($a, $b);

相反,您所看到的是行动中的comma operator

  

二进制“,”是逗号运算符。在标量上下文中,它评估其左参数,抛出该值,然后计算其右参数并返回该值。这就像C的逗号运算符一样。

要更清楚地看到这一点,请查看:

#!/usr/bin/perl
use strict; use warnings;

my $x = {a => 1};
my $y = {a => 2, b => 0};

my $z = ($x, $y);

print "\$x = $x\t\$y = $y\t\$z = $z\n";

my @z = ($x, $y);
print "@z\n";

首先,我使用warnings。因此,当我运行此脚本时,我收到警告:

  

Useless use of private variable in void context at C:\Temp\t.pl line 7.

始终启用警告。

现在,输出显示正在发生的事情:

$x = HASH(0x39cbc)      $y = HASH(0x39dac)      $z = HASH(0x39dac)
HASH(0x39cbc) HASH(0x39dac)

显然,$z引用与$y相同的匿名哈希。没有复制值。

并且$z[0]引用与$x相同的匿名哈希,而$z[1]引用与$y$z相同的匿名哈希。< / p>

请注意,仅括号不会创建列表上下文。在

的情况下
my @z = ($x, $y);

它们是必要的,因为=比逗号运算符绑定得更紧密。

my @z = $x, $y;

会将$x分配给$z[0]并弃掉$y(并发出警告),而

my @z = 1 .. 5;

会按预期工作。

最后,如果您想要为$z分配一个新的匿名哈希,其中包含$x$y指向的匿名哈希的副本,您可以

#!/usr/bin/perl
use strict; use warnings;
use Data::Dumper;

my $x = {a => 1};
my $y = {a => 2, b => 0};

my $z = { %$x, %$y };

print Dumper $z;

将输出:

$VAR1 = {
          'a' => 2,
          'b' => 0
        };

因为根据定义,散列键是唯一的。如果要保留与两个哈希的键关联的所有值,则需要执行稍微复杂的操作(并使用匿名arrayrefs作为“union”哈希中的值):

#!/usr/bin/perl
use strict; use warnings;
use Data::Dumper;

my $x = {a => 1};
my $y = {a => 2, b => 0};

my $z;

push @{ $z->{$_} }, $x->{$_} for keys %$x;
push @{ $z->{$_} }, $y->{$_} for keys %$y;

print Dumper $z;

输出:

VAR1 = {
         'a' => [
                  1,
                  2
                ],
         'b' => [
                  0
                ]
       };