oha has asked for the wisdom of the Perl Monks concerning the following question:

hi,

some days ago, speaking with another monk, i got this code:

push @{$a[0]}, "foo";
it should append the array whose name is $a[0]. I expected to get an error if @a is empty, i'll get a undefined from $a[0]!.
it's not:
use Data::Dumper; print Dumper(\@a); push @{$a[0]}, "foo"; print Dumper(\@a);
gives:
$VAR1 = []; $VAR1 = [ [ 'foo' ] ];
why perl vivify an anonymous array in @a?

update: added bold to important text

Replies are listed 'Best First'.
Re: push undefined and vivification
by BrowserUk (Patriarch) on Jan 17, 2004 at 22:34 UTC
    why perl vivify an anonymous array in @a?

    Cos that's what you asked it to do :)

    push @{$a[0]}, "foo"; say's treat the value in $a[0] as a reference to an array, and then push 'foo', onto the array located at that reference @{ <array_reference> }.

    If the value of $a[ 0 ] is undefined, perl autovivifies an anonymous array, stores a reference to it in $a[ 0 ] and then pushes 'foo' into that.

    Perl will only autovivify the anon. array if the value of the array element is undefined. if it has any value that would test as defined, including '' & 0, it will issue a warning.

    W:\current>perl use strict; use Data::Dumper; my @a = ( 'fred' ); push @{ $a[ 0 ] }, 'foo'; print Dumper \@a; ^Z Can't use string ("fred") as an ARRAY ref while "strict refs" in use a +t - line 4. W:\current>perl use strict; use Data::Dumper; my @a = ( '' ); push @{ $a[ 0 ] }, 'foo'; print Dumper \@a; ^Z Can't use string ("") as an ARRAY ref while "strict refs" in use at - +line 4.

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    Timing (and a little luck) are everything!

      Perl will only autovivify the anon. array if the value of the array element is undefined. if it has any value that would test as defined, including '' & 0, it will issue a warning.

      Actually, perl will die, not issue a warning:

      Can't use string (""%s"") as %s ref while ""strict refs"" in use

      (F) Only hard references are allowed by "strict refs". Symbolic references are disallowed. See the perlref manpage. - perldiag

      That (F) means A fatal error (trappable), i.e. die.

      Programmer beware.

      --
      3dan

      in use strict it's right. but without, the code:
      use Data::Dumper; @a=('bar'); print Dumper(\@a); push @{$a[0]}, "foo"; print Dumper(\@a); print Dumper(\@bar);
      actually append 'foo' to @bar:
      $VAR1 = [ 'bar' ]; $VAR1 = [ 'bar' ]; $VAR1 = [ 'foo' ];

      in that case, so, perl do one of three things:

    • append to the array named by the value of $a[0], or
    • append to the array-ref in $a[0], or
    • create an anonymous array and put the reference in $a[0]
      in use strict; the behavior of push is predictable, but without -- and using a string in $a[0] -- the behavior is not predictable.

      this may be a good reason to use strict, without perl may use the @{$something} as array-ref or variable name... a bit confusing, doesn't it?

        in use strict; the behavior of push is predictable, but without -- and using a string in $a[0] -- the behavior is not predictable
        Wrong. The behaviour is perfectly predictable. Observe
        use Data::Dumper; @a = 'bar'; @bar = 6; warn push @{$a[0]}, 7; warn Dumper( \@a, \@bar ); warn push @{"$a[0]"}, 8; warn Dumper( \@a, \@bar ); warn push @{"bar"}, 9; warn Dumper( \@a, \@bar ); undef $a[0]; warn push @{$a[0]}, 11; warn Dumper( \@a, \@bar ); __END__ 2 at - line 4. $VAR1 = [ 'bar' ]; $VAR2 = [ 6, 7 ]; 3 at - line 7. $VAR1 = [ 'bar' ]; $VAR2 = [ 6, 7, 8 ]; 4 at - line 10. $VAR1 = [ 'bar' ]; $VAR2 = [ 6, 7, 8, 9 ]; 1 at - line 13. $VAR1 = [ [ 11 ] ]; $VAR2 = [ 6, 7, 8, 9 ];

        without perl may use the @{$something} as array-ref or variable name... a bit confusing, doesn't it?
        Why? Observe
        @a = 'bar'; @bar = 6; warn 'PUSHING ONTO @BAR' if defined $a[0]; push @{$a[0]}, 'bar'; undef $a[0]; warn 'PUSHING ONTO $a[0]' if not defined $a[0]; push @{$a[0]}, 'bar'; use Data::Dumper; warn Dumper( \@a, \@bar ); __END__ PUSHING ONTO @BAR at - line 4. PUSHING ONTO $a[0] at - line 10. $VAR1 = [ [ 'bar' ] ]; $VAR2 = [ 6, 'bar' ];
•Re: push undefined and vivification
by merlyn (Sage) on Jan 17, 2004 at 22:20 UTC
Re: push undefined and vivification
by Anonymous Monk on Jan 18, 2004 at 09:03 UTC
    why perl vivify an anonymous array in @a?

    Because that's how perl works (what did you expect it to do?).

Re: push undefined and vivification
by mrpeabody (Friar) on Jan 19, 2004 at 01:04 UTC
    why perl vivify an anonymous array in @a?

    So you don't have to write

    if (not defined $a[0]) { $a[0] = []; }; push @{$a[0]}, "foo";