in reply to Re: Array dereference in foreach()
in thread Array dereference in foreach()

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.

Replies are listed 'Best First'.
Re^3: Array dereference in foreach()
by haukex (Archbishop) on Nov 14, 2017 at 16:20 UTC
    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

        That's how autovivification currently works. In order to assign the value to the LHS, you need to look what's in $g->{lkj}. To check for the existence of the key, you first need $g to be a hash reference, if it's undef, it autovivifies, else if it's not a hash ref, you get an exception (under strict). There's no need to create the lkj key in $g, as it wasn't used in an lvalue context, but if you tried to access $g->{lkj}{mno} or $g->{lkj}[2] ...

        Use

        no autovivification;

        if you don't want the structures to be created. See autovivification.

        ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,

        Hi, on a side note, you don't need to pass to Data::Dumper a reference to the structure you are dumping, if that structure is already a reference.

        my %hash = ( foo => 'bar' ); my $href = { baz => 'qux' }; print " hash: ", Dumper( \%hash ), "\n"; print "hashref: ", Dumper( $href ), "\n";

        Hope this helps!


        The way forward always starts with a minimal test.