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

At this node Anarion noticed some odd perl behaviour. The essence of the problem is summarised in the snippet below:

use Data::Dumper; my @matrix = (); $matrix[2]->[3]= "What's goin on?"; print "Before grep:\n", Dumper(\@matrix); grep{ /Huh?/ }@$_ for @matrix; print "\nAfter grep:\n", Dumper(\@matrix); __DATA__ Before grep: $VAR1 = [ undef, ${\$VAR1->[0]}, [ ${\$VAR1->[0]}, ${\$VAR1->[0]}, ${\$VAR1->[0]}, 'What\'s goin on?' ] ]; After grep: $VAR1 = [ [], [], [ undef, ${\$VAR1->[2][0]}, ${\$VAR1->[2][0]}, 'What\'s goin on?' ] ];

So the questions are: 1) why does the matrix get its original self referencing structure and 2) why does simply grepping through it change that structure?

cheers

tachyon

s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Replies are listed 'Best First'.
Re: A new perl {cough} feature?
by premchai21 (Curate) on Feb 17, 2002 at 16:20 UTC

    This seems to be a bug in Data::Dumper. With the perl debugger (before the grep, thanks tye):

    main::(-:1): my @matrix = (); DB<1> n main::(-:2): $matrix[2]->[3] = "What's goin' on?"; DB<1> n main::(-:3): grep {/Huh?/}@$_ for @matrix; DB<1> print @matrix ARRAY(0x8103f2c) DB<2> x @matrix 0 undef 1 undef 2 ARRAY(0x8103f2c) 0 empty slot 1 empty slot 2 empty slot 3 'What\'s goin\' on?' DB<3>

    With Data::Denter:

    Before grep: @ ? ? @ ? ? ? What's goin on? After grep: @ @ @ @ ? ? ? What's goin on?

    ... indicating undef (?) before the grep, as normal, and empty array refs (@) after the grep, as normal due to autovivification upon array dereference. Only Data::Dumper seems to get it wrong, or at least what seems to be wrong.

      Yes, but try this one:
      use Data::Denter; my @matrix = (); $matrix[2]->[3]= "What's goin on?"; print "Before grep:\n", Denter(\@matrix); #print grep{ /Huh?/ }@$_ for @matrix; print map { grep{ /Huh?/ }@$_ } @matrix; print "\nAfter grep:\n", Denter(\@matrix);


      Where is the bug then in Data::Dumper or in Data::Denter or in map, grep, for or autovivification?

      $anarion=\$anarion;

      s==q^QBY_^=,$_^=$[x7,print

      It's not unreasonable that it is a Data::Dumper flaw. Recently I was using Data::Dumper on some not so complex structures and some of the values it output were array-refs (where no array-ref ought to live) i.e. it output the scalar form of the array-ref, not even an evalable form.

      --
      perl -pe "s/\b;([st])/'\1/mg"

      Quick clarification: Note that the first set of output is from before grep gets run. It is the grep that autovivifies those empty array references.

              - tye (but my friends call me "Tye")
Re: A new perl {cough} feature?
by chipmunk (Parson) on Feb 18, 2002 at 05:17 UTC
    The answers are:

    1) Perl has a special value for undef, called SV_UNDEF. Rather than create a separate 'undef' for each uninitialized value, Perl stores a pointer to this special undef value. Thus, the output from Data::Dumper is, in a way, correct; all of the uninitialized array elements are pointing to the same value, SV_UNDEF.

    2) Auto-vivification. grep { 1 } @$_ for @matrix; treats each element of @matrix as an array reference, so the uninitialized elements are autovivified.

      2.5) and why for can iterate over it and map chokes?

      Take a look at my code above

      $anarion=\$anarion;

      s==q^QBY_^=,$_^=$[x7,print

Re: A new perl {cough} feature?
by jlongino (Parson) on Feb 17, 2002 at 18:31 UTC
    It's apparently an auto-vivification problem, caused by iterating over the entire structure? Using the following subroutine instead of the grep produces the same results:
    dump_matrix(); sub dump_matrix { for my $i (0..2) { print "row: $i [ "; for my $j (0..3) { print "$matrix[$i][$j], "; } print "]\n"; } }
    What's interesting is how two consecutive calls to Data::Dumper without intervening code does not reproduce the anomaly (even if you pass by reference). Makes me wonder how Data::Dumper is traversing the structure.

    --Jim

    Update: Ah. Thanks tachyon, I would've researched it but I've been competing for computer time today. Five year olds always win :(

      Makes me wonder how Data::Dumper is traversing the structure

      Data::Dumper is an XS module so it does it in C

      cheers

      tachyon

      s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

        Actually its both.

        When I get some time i'll check to whether the pure perl version does the same thing.

        Yves / DeMerphq
        --
        When to use Prototypes?

Re: A new perl {cough} feature?
by demerphq (Chancellor) on Feb 18, 2002 at 09:56 UTC
    As chipmunk pointed out the structure _is_ self-referencing from the point of view of dumper. Dumper is simply reusing the first 'undef' it encounters. (Very annoying, I know.)

    Also, IMO when using Dumper one should _always_ set Purity to be true

    use Data::Dumper; $Data::Dumper::Purity=1;
    Its suprising the different results that can occur.

    Yves / DeMerphq
    --
    When to use Prototypes?

Re: A new perl {cough} feature?
by BeernuT (Pilgrim) on Feb 17, 2002 at 16:30 UTC
    did you really mean
    grep { /Huh?/ } @matrix;
    instead of
    grep { /Huh?/ } @$_ for @matrix;
    grep

    -bn
      @matrix = ( ["\n\nNo "], ["I ", "did "], ["not mean that, ", "get it n +ow?"] ); grep{print}@matrix; grep{print}@$_ for @matrix;

      perlman:perlref

      cheers

      tachyon

      s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Re (tilly) 1: A new perl {cough} feature?
by tilly (Archbishop) on Feb 18, 2002 at 01:35 UTC
    As another data point, Perl 5.005_03 crashes on this, and 5.7 (as of a few months ago) does what 5.6 does.

    I would report this as a bug to p5p, and also make sure to actually initialize all rows in the array of arrays before proceeding to use it as such.