When you used an undefined value as if it's a reference, Perl makes the reference sort that you wanted then tries to perform the operation. This is called "auto-vivification".
Here's a small demonstration. A variable starts out as undefined. You then treat it as an array reference (the dereference to get the 0th element):
use Data::Dumper;
my $empty;
print Dumper( $empty );
my $value = $empty->[0];
print Dumper( $empty );
Perl converts $empty
to an array reference then tries to get the 0th element from that. You are left with an array reference where you formerly had undef
:
$VAR1 = undef;
$VAR1 = [];
This is intended behavior.
Take it one step further. Put that undef
inside an array and treat that element as if it's an array reference:
use Data::Dumper;
my @array = ( 1, undef, 'red' );
print Dumper( \@array );
my $value = $array[1]->[0];
print Dumper( \@array );
Now the second element is an empty array reference:
$VAR1 = [
1,
undef,
'red'
];
$VAR1 = [
1,
[],
'red'
];
Take it another step further. Don't store the undef
value. Instead, access an array position past the last item in the array:
use Data::Dumper;
my @array = ( 1, 'red' );
print Dumper( \@array );
my $value = $array[2]->[0];
print Dumper( \@array );
Now you get an array reference element in your array. It's one element longer now:
$VAR1 = [
1,
'red'
];
$VAR1 = [
1,
'red',
[]
];
Had you gone further out (say, element 5), the interstitial elements up to the element you wanted would have been "filled in" with undef
:
use Data::Dumper;
my @array = ( 1, 'red' );
print Dumper( \@array );
my $value = $array[5]->[0];
print Dumper( \@array );
$VAR1 = [
1,
'red'
];
$VAR1 = [
1,
'red',
undef,
undef,
undef,
[]
];
A hash works the same way, and that's what you are seeing. When you want to check if there is a second-level key under James
, Perl needs to create the James
key and give it an empty hash ref value to it can check that. That second-level key is not there, but the first-level key of 'James' sticks around:
use Data::Dumper;
my %hash = (
John => { Jay => '137' },
);
print Dumper( \%hash );
if( exists $hash{James}{Jay} ) {
print $hash{James}{Jay};
}
print Dumper( \%hash );
Now you see an extra key:
$VAR1 = {
'John' => {
'Jay' => '137'
}
};
$VAR1 = {
'James' => {},
'John' => {
'Jay' => '137'
}
};
In this case, you don't like this feature, but you can turn it off with the no autovivification
pragma. It's a CPAN module that you need to install first:
no autovivification;
use Data::Dumper;
my %hash = (
John => { Jay => '137' },
);
print Dumper( \%hash );
if( exists $hash{James}{Jay} ) {
print $hash{James}{Jay};
}
print Dumper( \%hash );
You don't get the extra key:
$VAR1 = {
'John' => {
'Jay' => '137'
}
};
$VAR1 = {
'John' => {
'Jay' => '137'
}
};
You might also like to read How can I check if a key exists in a deep Perl hash?. I show a method that allows you to inspect a nested hash without creating intermediate levels.