我试图使用模块:https://metacpan.org/pod/autovivification关闭自动生存功能,但对于grep来说,它失败了:
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use feature 'say';
use autodie ':all';
use DDP;
no autovivification;
my %h = (
'a' => 1,
'b' => 2,
);
p %h; # pretty print the original hash
my @fake_keys = ('x', 'y', 'z');
if (grep {defined} @h{@fake_keys}) {
say "found fake keys";
}
p %h; # show that 'x', 'y', & 'z' are added as undef keys如何为grep关闭自动生存功能?
发布于 2021-02-11 18:06:25
解决方案:
if (grep { defined($h{$_}) } @fake_keys) {
say "found fake keys";
}解释如下。
在Perl文档中使用的自动生动化是在取消引用未定义的标量时创建anon和对它们的引用。
例如,自动生动说明$x->[0]等同于( $x //= [] )->[0]。
例如,自动生动说明$h{p}{q}等同于( $h{p} //= {} )->{q}。
代码中没有取消引用,所以代码中不可能出现自动激活,所以no autovivification;没有帮助。
代码中有一个用作lvalue的散列元素。"lvalue“是指可转让的价值。它是以这样一个事实命名的,即这样的表达式通常可以在赋值的_l_eft上找到。
$h{key} = ...;
# ^^^^^^^
# lvalue但是在Perl的其他地方也可以找到它们。
for ($h{key}) {
# ^^^^^^^
# lvalue
}map { } $h{key}
# ^^^^^^^
# lvaluegrep { } $h{key}
# ^^^^^^^
# lvaluesome_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}。
$ perl -M5.010 -e'for ($h{key}) { } say 0+keys(%h);'
1Sub使用昂贵的魔法来避免这种情况。
$ 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发布于 2021-02-11 15:07:37
导致这种情况的不是grep,而是散列片中值的混叠。
这也有同样的效果:
for (@h{@fake_keys}){
my $t = $_;
}您可以通过复制切片来绕过它:
use strict;
use warnings FATAL => 'all';
use feature 'say';
use autodie ':all';
use DDP;
my %h = (
'a' => 1,
'b' => 2,
);
p %h; # pretty print the original hash
my @fake_keys = ('x', 'y', 'z');
if (grep {defined} @{[@h{@fake_keys}]}) {
say "found fake keys";
}
p %h; # show that 'x', 'y', & 'z' are added as undef keys或者通过Ikegami访问grep块中的每个值,比如shown。
https://stackoverflow.com/questions/66156905
复制相似问题