解决方案:
if (grep { defined($h{$_}) } @fake_keys) {
say "found fake keys";
}
解释如下。
在 Perl 文档中使用的 Autovivification 是在取消引用未定义的标量时创建匿名变量和对它们的引用。
例如,autovivification 规定$x->[0]
相当于( $x //= [] )->[0]
.
例如,autovivification 规定$h{p}{q}
相当于( $h{p} //= {} )->{q}
.
您的代码中没有取消引用,因此您的代码中不可能发生 autovivifaction,因此no autovivification;
无济于事。
您在代码中拥有的是用作左值的哈希元素。“左值”表示可分配的值。它的命名是因为这样的表达式通常出现在赋值的左侧。
$h{key} = ...;
# ^^^^^^^
# lvalue
但它们也可以在 Perl 的其他地方找到。
for ($h{key}) {
# ^^^^^^^
# lvalue
}
map { } $h{key}
# ^^^^^^^
# lvalue
grep { } $h{key}
# ^^^^^^^
# lvalue
some_sub($h{key});
# ^^^^^^^
# lvalue
这是因为每个循环结构的块都可以通过修改来修改正在处理的项目$_
,并且子可以通过修改 的元素来修改他们的参数@_
。
for ($h{key}) {
$_ = uc($_); # Modifies $h{key}
}
grep { $_ = uc($_) } $h{key} # Modifies $h{key} # Bad practice, but possible.
map { $_ = uc($_) } $h{key} # Modifies $h{key}
sub some_sub {
$_[0] = uc($_[0]); # Modifies $h{key}
}
some_sub($h{$k});
为此,$h{$k}
必须在进入循环体或调用 sub 之前存在。
$ perl -M5.010 -e'for ($h{key}) { } say 0+keys(%h);'
1
子调用使用昂贵的魔法来避免这种情况。
$ perl -M5.010 -e'sub f { } f($h{key}); say 0+keys(%h);'
0
但是grep
,map
不要。
$ perl -M5.010 -e'grep { 1 } $h{key}; say 0+keys(%h);'
1
$ perl -M5.010 -e'map {; } $h{key}; say 0+keys(%h);'
1