4

我正在与一些使用哈希引用的 Perl 搏斗。

最后发现我的问题是这条线:

$myhash{$key} |= {};

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

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

将其更改为:

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

... 让事情顺利进行。

所以我没有问题。但我很好奇发生了什么。

谁能解释一下?

4

4 回答 4

16

Perl 有速记赋值运算符。由于 Perl 具有让逻辑运算符返回最后评估的值的特性,该||=运算符通常用于设置变量的默认值。问题是您使用|=的是按位或而不是||=逻辑

从 Perl 5.10 开始,最好//=改用它。//是逻辑定义或运算符,在当前值已定义但为假的极端情况下不会失败。

于 2008-09-30T20:40:13.443 回答
16

您看到有关使用字符串作为哈希引用的错误的原因是您使用了错误的运算符。|=意思是“按位或赋值”。换句话说,

  $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' => {}
          };
于 2008-09-30T20:47:12.740 回答
4

我认为您的问题是使用“ |=”(按位或赋值)而不是“ ||=”(如果为 false,则赋值)。

请注意,您的新代码并不完全相同。不同之处在于“ $myhash{$key} ||= {}”将用哈希引用替换现有但为假的值,但新的不会。在实践中,这可能无关紧要。

于 2008-09-30T20:41:23.287 回答
2

试试这个:

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

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

编辑:我看到你已经取出了my. 尝试||=而不是怎么样|=?前者是“惰性”初始化的惯用语。

于 2008-09-30T20:30:03.187 回答