2

假设我有一个 Perl 脚本:

my $hash = {};
$hash->{'a'} = {aa => 'b'};
$hash->{'b'} = undef;

for (qw(a b c)) {
    if(defined $hash->{$_}->{aa})
    {
        say "defined $_";
    }
    else
    {
        say "undef $_";
    }
}
print Dumper $hash;

但是我的输出会自动创建“c”,这是我不想要的。

defined a
undef b
undef c
$VAR1 = {
      'c' => {},
      'a' => {
               'aa' => 'b'
             },
      'b' => {}
    };

此外,我的发行版不允许我禁用自动生存。有没有办法制作一个检查每个级别的子程序?

4

3 回答 3

11

no autovivification在所需范围内调用:

for (qw(a b c)) {
    no autovivification;
    if(defined $hash->{$_}->{aa})
    {
        say "defined $_";
    }
    else
    {
        say "undef $_";
    }
}

如果autovivificationpragma 不可用,通常的习惯用法是在更深层次运行检查之前测试顶级哈希是否存在:

if ($hash && $hash->{$_} && defined($hash->{$_}->{aa}) {
   ...
}
于 2012-11-07T22:30:36.133 回答
3

出什么问题了:

if (exists $hash->{$_} and defined $hash->{$_}->{aa})
于 2012-11-08T00:07:05.083 回答
1

这是一个简单的函数,它检查每个级别的存在并在不自动激活中间级别的情况下停止。原型不是必需的;它使它的行为(有点)像内置的defined. 此版本仅适用于嵌套散列(除了祝福散列和看起来像散列的重载对象)。

sub noVivDefined(+@) {
    my ($x, @keys) = @_;
    foreach my $k (@keys) {
        return unless ref $x eq 'HASH';
        return unless exists $x->{$k};
        $x = $x->{$k};
    }
    return defined $x;
}

my %h = (
    a => { b => 1 },
    b => { b => 0 },
    c => { b => undef },
    d => { c => 1 },
);


say noVivDefined %h, qw(a b);   # prints '1'
say noVivDefined %h, qw(a b c); # prints ''
say noVivDefined %h, qw(x y z); # prints ''
say noVivDefined %h, qw(b b);   # prints '1'
say noVivDefined %h, qw(c b);   # prints ''
say noVivDefined %h, qw(d b);   # prints ''
say noVivDefined \%h, qw(a b);  # prints '1'
于 2012-11-07T23:07:14.037 回答