in reply to Array dereference in foreach()

From perlref (emphasis mine): "... references could spring into existence when in an lvalue context. ... This process is called autovivification." foreach provides lvalue context to what it is looping over: "If any element of LIST is an lvalue, you can modify it by modifying VAR inside the loop. ... the foreach loop index variable is an implicit alias for each item in the list that you're looping over."

$ perl -wMstrict -MData::Dump -e ' @{$a->{list}} = (); dd $a' { list => [] } $ perl -wMstrict -MData::Dump -e ' for (@{$a->{list}}) {}; dd $a' { list => [] } $ perl -wMstrict -MData::Dump -e ' my @x = @{$a->{list}}; dd $a' Can't use an undefined value as an ARRAY reference at -e line 1.

Replies are listed 'Best First'.
Re^2: Array dereference in foreach()
by Anonymous Monk on Nov 14, 2017 at 16:02 UTC
    In your third one-liner example, $a plausibly could be undefined. I think that the OPs problem is that an array-type variable, @a, is being assigned an array reference, $href. Not sure why Perl is complaining about an "undefined variable" in that case, however.
      I think that the OPs problem is that an array-type variable, @a, is being assigned an array reference, $href.

      Sorry, but that's not the right way to look at it. @a is not being assigned a reference, instead, the @{...} dereferences the array reference, and it can be used in place of any normal array (perlref), so in effect my @x = @{...} is like assigning an array to an array.

      In your third one-liner example, $a plausibly could be undefined.

      I'm not sure what you mean, $a is initially undefined in every example. Autovivification is what is causing both $a to go from being uninitialized to holding a hashref (because it's being dereferenced as such with ->{...}) and $a->{list} to come into existence as a hash entry with a value of [] (empty array ref). The third example does not work because in my @x = @{$a->{list}};, the @{$a->{list}} is not in lvalue context. Personally, I think in this case the autovivification behavior is fairly consistent with DWIM:

      • In @x = @{$a->{list}}, I am asking Perl to access and dereference a reference, but there is no such reference there - the thing I expected to be there isn't, so Perl complains.
      • In @{$a->{list}} = (), I am explicitly telling Perl that I want to assign something to that reference and I want it to be an array reference, so it makes sense for that thing to come into existence.
      • The only "potentially surprising" thing here is the foreach behavior, which I explained in the first reply.

      Edit: Just moved a sentence so the order makes more sense.

        Hi haukex,

        Thank you to for your detailed explanation. That makes sense. However I found another interesting feature.

        my $h; my $g; $h->{abc} = $g->{lkj}; print "h: ", Dumper(\$h), "\n"; print "g: ", Dumper(\$g), "\n";
        and the output is
        h: $VAR1 = \{ 'abc' => undef }; g: $VAR1 = \{};
        The left side ($h) is autovivified and undef is assigned to key 'abc'. It is correct. But what has happened on the right? Is it semi-autovivified or what? Empty anonymous hashref is assigned to $g. Where is 'lkj'? Is $g->{lkj} in lvalue context? Why there is no exception?

        Regards