Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inconsistent behavior concerning "Can't use an undefined value as an ARRAY reference"

Tags:

perl

perl5.16

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? Thanks for your input.

like image 224
Morrowind789 Avatar asked Jan 06 '16 19:01

Morrowind789


1 Answers

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.


  1. If the final deferencing is followed by an indexing (e.g. ->[] 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.
like image 103
ikegami Avatar answered Nov 11 '22 20:11

ikegami