Let's say I have a Perl script that does:
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;
But, my output autocreates 'c', which I don't want.
defined a
undef b
undef c
$VAR1 = {
'c' => {},
'a' => {
'aa' => 'b'
},
'b' => {}
};
Also my distribution does not allow me to disable autovivification. Is there a way to make a subroutine that checks each level?
Here's a simple function that checks each level for existence and stops without autovivifying intermediate levels. The prototype isn't necessary; it makes it act (sort of) like the built-in defined
. This version only works for nested hashes (except blessed hashes and overloaded objects that look like hashes).
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'