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 $_";
    }
}

プラグマが利用できない場合autovivification、通常のイディオムは、より深いレベルでチェックを実行する前に、トップレベルのハッシュの存在をテストすることです:

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ます。このバージョンは、ネストされたハッシュに対してのみ機能します (bless されたハッシュと、ハッシュのように見えるオーバーロードされたオブジェクトを除く)。

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 に答える