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

Greetings all,
I have run across something rather puzzling to me.
This would be easier to illustrate given the code:
#!/usr/bin/perl -w use strict; use Dumpvalue; ###how I would normally do it. my @cells; for(my $i=0; $i<3; $i++){ push(@cells,[[],[],[]]); } ###a different approach. my @othercells; @othercells = ([[],[],[]]) x 3; ###lets check shall we? print "Content-Type:text/html\n\n"; dump_ref(\@cells); dump_ref(\@othercells); exit; ###peek under the hood. sub dump_ref { my $ref = shift; my $dumper = new Dumpvalue; print "<pre>"; $dumper->dumpValues($ref); print "</pre>"; print "<br />"; }
This gives me
0 ARRAY(0x8135f2c) 0 ARRAY(0x813fb50) 0 ARRAY(0x812bd00) empty array 1 ARRAY(0x812be2c) empty array 2 ARRAY(0x812bc1c) empty array 1 ARRAY(0x816dc88) 0 ARRAY(0x812bde4) empty array 1 ARRAY(0x813fb5c) empty array 2 ARRAY(0x813f8ec) empty array 2 ARRAY(0x816dce8) 0 ARRAY(0x8135efc) empty array 1 ARRAY(0x816dc7c) empty array 2 ARRAY(0x816dcd0) empty array 0 ARRAY(0x8135f20) 0 ARRAY(0x816dd48) 0 ARRAY(0x813fa48) empty array 1 ARRAY(0x816dcdc) empty array 2 ARRAY(0x816dd30) empty array 1 ARRAY(0x816dd48) -> REUSED_ADDRESS 2 ARRAY(0x816dd48) -> REUSED_ADDRESS
My question is this: Why does the latter method reuse the address of the anonymous array?
My present understanding led me to think that both methodologies would return the same structure (namely the first dumped results), however I was wrong! So could someone please help dispel my obfuscated understanding regarding the latter idiom?
Thanks in advance
-injunjoel

Replies are listed 'Best First'.
Re: Comparing two approaches to nested data creation
by Abigail-II (Bishop) on Nov 20, 2003 at 23:41 UTC
    If you use the x operator, the left argument is evaluated only once, and then copied. Watch:
    my $c = 0; sub f {print ++ $c, "\n";} my @f = (f) x 3; __END__ 1
    f is called just once, not three times.

    So, in your case, you end up with three references to the same anon array.

    Abigail

Re: Comparing two approaches to nested data creation
by Coruscate (Sexton) on Nov 20, 2003 at 23:41 UTC

    The first thing that pops into mind is that when you say @foo = ([ [], [], [] ]) x 3;, what you are really doing is creating the same structure only once, and then copying that 2 more times. ie: the 'x' operator is copying the LHS, not re-evaluating it. The following snippet should answer your question. Note how it prints "1, 1, 1, 1" rather than "1, 2, 3, 4":

    #!c:/perl/bin/perl -w $|++ use strict; my $bar; print join(', ', (++$bar) x 4), "\n";

    Update:
    As a different approach of how to create your @othercells array:

    my @othercells = map { [[],[],[]] } 1..3; # or my @othercells; push @othercells, [[],[],[]] for 1..3;