http://qs321.pair.com?node_id=675725


in reply to Re^2: references--hard vs anonymous operational weirdness
in thread references--hard vs anonymous operational weirdness

Quite right, I'd got caught by an optimization. I ran (adjusting code to your example)

for my $tab ( 1 .. 3 ) { my @array = frobnicate($tab); printf "Array ref: %s\n", \@array; printf "Annoymous: %s\n", [@array]; } sub frobnicate { return ( 0 .. shift ); } __END__ Array ref: ARRAY(0x826a924) Annoymous: ARRAY(0x8183a54) Array ref: ARRAY(0x826a924) Annoymous: ARRAY(0x826d818) Array ref: ARRAY(0x826a924) Annoymous: ARRAY(0x82115f8)
The same address even though @array is declared in the loop. The variable is being reused. Assigning \@array to something prevents the optimization.
my %data; for my $tab ( 1 .. 3 ) { my @array = frobnicate($tab); printf "Array ref: %s\n", \@array; printf "Annoymous: %s\n", [@array]; $data{$tab} = \@array; } sub frobnicate { return ( 0 .. shift ); } __END__ Array ref: ARRAY(0x826a924) Annoymous: ARRAY(0x8183a54) Array ref: ARRAY(0x819f318) Annoymous: ARRAY(0x8183798) Array ref: ARRAY(0x826ade8) Annoymous: ARRAY(0x819f304)
Something to bear in mind when benchmarking.

Replies are listed 'Best First'.
Re^4: references--hard vs anonymous operational weirdness
by chromatic (Archbishop) on Mar 23, 2008 at 03:55 UTC
    Assigning \@array to something prevents the optimization.

    Which optimization is that? Can you show the (incorrect) code which triggers this optimization?

      The first of the two examples in the grandparent of this post is the "incorrect" code. To cut it down to a minimum

      for my $tab ( 1 .. 3 ) { my @array = ( 0 .. $tab); printf "Array ref: %s\n", \@array; } __END__ Array ref: ARRAY(0x826acf4) Array ref: ARRAY(0x826acf4) Array ref: ARRAY(0x826acf4)
      As you can see the same address is being reused. The latest perl review has an article about closures (PDF) that mentions it in passing.

      I don't see how the code is incorrect. In the first example the value of @array is discarded but I could quite legitimately do something like

      for my $value ( @values ) { my @array = frobinate($value); foreach my $bit (@array) { drill($bit); } }
      and the memory location of @array is reused.

        As you can see the same address is being reused.

        Even if it wasn't optimized, that wouldcould be the case too.

        In the non-optimized world, the my variable would get freed at the end of the for loop (since there are no longer any references to it) and reallocated at the top. Logically, the memory manager wouldcould find the same free block the second time around as the first since nothing changed.

        While there is an optimization involved here to save some memory management work, it doesn't cause any change in the observed behaviour. What you call an optimization is just garbage collection, not an optimization at all.

        Updates marked using INS and DEL elements. See chromatic's reply for details.