我正在与一些使用哈希引用的Perl搏斗。
最后事实证明,我的问题是这句话:
$myhash{$key} |= {};
也就是说,"$myhash{$key} 分配对空哈希的引用,除非它已经有值"。
但是,取消引用此内容并尝试将其用作哈希引用会导致解释器错误,从而将字符串用作哈希引用。
将其更改为:
if( ! exists $myhash{$key}) {
$myhash{$key} = {};
}
。让事情顺利进行。
所以我没有问题。但我很好奇发生了什么。
谁能解释一下?
您看到有关使用字符串作为哈希引用的错误的原因是因为您使用了错误的运算符。 |=
的意思是"按位或分配"。 换句话说,
$foo |= $bar;
与
$foo = $foo | $bar
在您的示例中发生的情况是,新的匿名哈希引用被字符串化,然后按位或 $myhash{$key}
的值进行 OR。更令人困惑的是,如果当时未定义$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' => {}
};
Perl 有速记赋值运算符。||=
运算符通常用于设置变量的默认值,因为 Perl 的功能是让逻辑运算符返回最后一个计算值。问题是你使用了按位或|=
而不是逻辑或||=
从 Perl 5.10 开始,最好改用 //=
。 //
是逻辑定义或运算符,在当前值已定义但为 false 的极端情况下不会失败。
你的问题是使用" |=
"(按位或赋值)而不是" ||=
"(如果为假则分配)。
请注意,您的新代码并不完全相同。 不同之处在于"$myhash{$key} ||= {}
"将用哈希引用替换现有但错误的值,但新的不会。 在实践中,这可能无关紧要。
试试这个:
my %myhash;
$myhash{$key} ||= {};
据我所知,您不能在 my
子句中声明哈希元素。首先声明哈希,然后添加元素。
编辑:我看到你已经取出了my
。尝试||=
而不是|=
怎么样?前者是"惰性"初始化的习惯用语。