Why does the following code:
use strict;
use warnings;
no warnings 'uninitialized';
use Data::Dumper;
my $user;
my @data = @{$user->{ENTERPRISE}}; # Error on this line
print Dumper($user), qq{Done!\n};
Throw the error "Can't use an undefined value as an ARRAY reference
", while the following code:
use strict;
use warnings;
no warnings 'uninitialized';
use Data::Dumper;
my $user;
foreach my $enterprise(@{$user->{ENTERPRISES}}) {
print qq{Enterprise:}, $enterprise;
}
print Dumper($user), qq{Done!\n};
Does not throw anything, but instead returns:
$VAR1 = {
'ENTERPRISES' => []
};
Done!
Both have the offending code in them, but only one is throwing the error.
Possible Answer: Perl's autovivification?
Am I on the right track here?
Yes, what happened in the second case is called autovivification, and it only happened in the second case because autovivification only happens for lvalues[1].
So
@{ $x } = $y;
means
@{ $x //= [] } = $y;
but
$y = @{ $x };
doesn't mean
$y = @{ $x //= [] };
Keep in mind that foreach aliases its loop variable to each element of the list over which it iterates, so those elements are evaluated as lvalues.
Autovivification is documented in perlref, and you can control autovivification through the autovivification pragma.
->[]
or ->{}
), the reference expression itself is evaluated as an lvalue even if the indexed whole isn't. That means that $y = $x->[0];
and $y = ${ $x }[0];
can autovivify $x
even if $y = @{ $x };
won't.