Friday, March 2, 2012

Perl: Initializing 2-dimensional arrays using the repeat operator 'x'

I was trying to initialize a two dimensional Perl array with the repeat operator 'x', i.e.:

my @array = ([]) x 2;

Then I did something to the effect of,

for (my $i=0; $i<6; ++$i) { push(@{$array[$i % 2]}, 1); }

Thinking that I will create the equivalent of the following structure:

@array = ( [ 1, 1, 1 ], [ 1, 1, 1 ] );

However, doing:

print "@{$array[0]}\n";
print "@{$array[1]}\n";

gave,

1 1 1 1 1 1
1 1 1 1 1 1


How did that happen?


It seems that the left argument to the repeat operator, in this case, ( [] ) is evaluated before the repetition. Hence the initialization of @array achieved an effect similar to the following:


my $aRef = [];
my @array = ( $aRef, $aRef );


That is, the same reference to an empty array is repeated instead of a fresh reference. Hence the same array was pushed 6 times. 


As it turns out, it is better not to initialize the array at all and let the dynamic type system figure out the element type from a push,

my @array = ();
for (my $i=0; $i<6; ++$i) { push(@{$array[$i % 2]}, 1); }


Which resulted in the correct outcome, ( [ 1, 1, 1 ], [ 1, 1, 1 ] ), i.e., an array with two distinct array references.