【问题标题】:perl list context of hash refsperl 列出哈希引用的上下文
【发布时间】:2010-12-16 21:58:04
【问题描述】:

为什么会这样?也就是第 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 会明白我的意思,但是列表中只有裸露的 refs,为什么它会起作用?

或者也许它只是看起来有效,而我真的做了其他事情?

【问题讨论】:

  • 哦,小心“太简单”的测试。如果我使用了 $a = {'a'=>1, 'c'=>3);我会看到失败的。
  • 看起来是一个精心构造的问题。

标签: perl perl-hash


【解决方案1】:

中没有列表上下文
$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)
哈希(0x39cbc)哈希(0x39dac)

显然,$z$y 所指的匿名哈希相同。没有复制值。

而且,$z[0]$x$z[1] 指代相同的匿名哈希,与 $y$z 指代相同的匿名哈希。

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

的情况下
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 作为“联合”哈希中的值):

#!/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 = {
         '一个' => [
                  1、
                  2
                ],
         'b' => [
                  0
                ]
       };

【讨论】:

  • 是的!就像我想的那样,它实际上是在“做”别的事情。
  • 认为比较会更清楚。如果我搞砸了,请随时纠正/回滚
  • @bemace 我认为最好澄清一下没有制作底层匿名哈希的副本。
  • 要得到你想要的结果,你可以说($c) = ($a,$b)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-01
  • 2017-01-06
  • 2011-10-11
  • 2014-07-27
  • 1970-01-01
相关资源
最近更新 更多