首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >对于Perl中的grep,“无自动生存”实用化失败。

对于Perl中的grep,“无自动生存”实用化失败。
EN

Stack Overflow用户
提问于 2021-02-11 14:43:00
回答 2查看 252关注 0票数 8

我试图使用模块:https://metacpan.org/pod/autovivification关闭自动生存功能,但对于grep来说,它失败了:

代码语言:javascript
复制
#!/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关闭自动生存功能?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-02-11 18:06:25

解决方案:

代码语言:javascript
复制
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上找到。

代码语言:javascript
复制
  $h{key} = ...;
# ^^^^^^^
# lvalue

但是在Perl的其他地方也可以找到它们。

代码语言:javascript
复制
for ($h{key}) {
   # ^^^^^^^
   # lvalue
}
代码语言:javascript
复制
map { } $h{key}
      # ^^^^^^^
      # lvalue
代码语言:javascript
复制
grep { } $h{key}
       # ^^^^^^^
       # lvalue
代码语言:javascript
复制
some_sub($h{key});
       # ^^^^^^^
       # lvalue

这是因为每个循环结构的块都可以通过修改$_来修改正在处理的项,而子类可以修改它们的参数--我修改了@_的元素。

代码语言:javascript
复制
for ($h{key}) {
   $_ = uc($_);                 # Modifies $h{key}
}
代码语言:javascript
复制
grep { $_ = uc($_) } $h{key}    # Modifies $h{key}  # Bad practice, but possible.
代码语言:javascript
复制
map { $_ = uc($_) } $h{key}     # Modifies $h{key}
代码语言:javascript
复制
sub some_sub {
   $_[0] = uc($_[0]);           # Modifies $h{key}
}

some_sub($h{$k});

要做到这一点,必须在输入循环体或调用子之前存在$h{$k}

代码语言:javascript
复制
$ perl -M5.010 -e'for ($h{key}) { }  say 0+keys(%h);'
1

Sub使用昂贵的魔法来避免这种情况。

代码语言:javascript
复制
$ perl -M5.010 -e'sub f { }  f($h{key});  say 0+keys(%h);'
0

grepmap没有。

代码语言:javascript
复制
$ perl -M5.010 -e'grep { 1 } $h{key};  say 0+keys(%h);'
1
代码语言:javascript
复制
$ perl -M5.010 -e'map {; } $h{key};  say 0+keys(%h);'
1
票数 6
EN

Stack Overflow用户

发布于 2021-02-11 15:07:37

导致这种情况的不是grep,而是散列片中值的混叠。

这也有同样的效果:

代码语言:javascript
复制
for (@h{@fake_keys}){
 my $t = $_;
}

您可以通过复制切片来绕过它:

代码语言:javascript
复制
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

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66156905

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档