Perl中的$ hash {$ key} | = {}`是做什么的?

时间:2020-03-06 14:56:47  来源:igfitidea点击:

我正在与一些使用哈希引用的Perl进行角力。

最后,事实证明我的问题是这条线:

$myhash{$key} |= {};

也就是说,"向$ myhash {$ key}分配对空哈希的引用,除非它已经具有一个值"。

但是,取消引用并尝试将其用作哈希引用会导致将字符串用作哈希引用的解释器错误。

更改为:

if( ! exists $myhash{$key}) {
  $myhash{$key} = {};
}

...使事情起作用。

所以我没有问题。但是我对正在发生的事情很好奇。

谁能解释?

解决方案

试试这个:

my %myhash;
$myhash{$key} ||= {};

据我所知,我们不能在my子句中声明哈希元素。我们首先声明哈希,然后在其中添加元素。

编辑:我看到你拿出了"我的"。尝试使用|| =而不是| =`怎么样?前者是"惰性"初始化的惯用语。

Perl具有速记赋值运算符。由于Perl具有让逻辑运算符返回所评估的最后一个值的功能,因此经常使用|| =运算符来设置变量的默认值。问题是我们使用的是按位或者的" | =",而不是逻辑或者的" || ="。

从Perl 5.10开始,最好改用// =。 " //"是逻辑定义或者运算符,在定义了当前值但为false的特殊情况下不会失败。

我们看到有关将字符串用作哈希引用的错误的原因是因为我们使用了错误的运算符。 " | ="表示"按位分配"。换一种说法,

$foo |= $bar;

是相同的

$foo = $foo | $bar

示例中发生的事情是新的匿名哈希引用被字符串化,然后与$ myhash {$ key}的值进行按位或者运算。更令人困惑的是,如果当时未定义$ myhash {$ key},则该值是哈希引用的简单字符串化,看起来像HASH(0x80fc284)。因此,如果对结构进行粗略检查,它可能看起来像哈希引用,但不是。这是通过Data :: Dumper得到的一些有用的输出:

perl -MData::Dumper -le '$hash{foo} |= { }; print Dumper \%hash'
   $VAR1 = {
             'foo' => 'HASH(0x80fc284)'
           };

这是使用正确的运算符时得到的结果:

perl -MData::Dumper -le '$hash{foo} ||= { }; print Dumper \%hash'
  $VAR1 = {
            'foo' => {}
          };