BioRod BioRod - 28 days ago 10
Perl Question

understanding data structures in perl

I'm trying to understand the 'Common Mistake' section in the perldsc documentation. What is the author trying to convey when he mentions:


The two most common mistakes made in constructing something like an array of arrays is either accidentally counting the number of elements or else taking a reference to the same memory location repeatedly. Here's the case where you just get the count instead of a nested array:


for my $i (1..10) {
my @array = somefunc($i);
$AoA[$i] = @array; # WRONG!
}


From what I understand is that when it iterate it will take the first value of (1..10) which is 1 and will pass it to a function like this:

my @array = somefunc(1);


Since that function is not defined, I'll create the logic.

sub somefunc {
my $a = shift;
print $a * $a;
}


which will essentially do this:

1 * 1


and the result is '1'.

To my understanding my @array will look like:

@array = ('1');


And the next line will do:

$AoA[$i] = @array;


I'm assuming that $AoA[$1] is an anonymous array ( he/she didn't declare with 'my', btw) and the @array will be the first element of the this anonymous array which the author said it' WRONG. And the for each loop with iterate to '2'.

somefunc(2);


Which will be '4' and passed to:

$AoA[$i] = @array


What is the point of the author with this code which is wrong. I'm trying to understand what is wrong but more importantly, I'm trying to understand the code. Any help will be appreciated.

UPDATE

I think I understand why this is a common mistake because when I use print and Dumper, I can visually see what the author is trying to convey, here is the revised code.

#!/usr/bin/perl -w
use strict;
use Data::Dumper;

for my $i (1..10) {
my @AoA;
my @array = somefunc($i);
print "The array is Dumper(@array)\n";
$AoA[$i] = @array; # WRONG!
print Dumper($AoA[$i]);
}


sub somefunc {
my $a = shift;
return $a * $a;
}


In the Common Mistakes paragraph of perldoc perldsc, he/she states


Here's the case where you just get the count instead of a nested array:


Below is the output of the Dumper.

The array is Dumper(1)
$VAR1 = 1;
The array is Dumper(4)
$VAR1 = 1;
The array is Dumper(9)
$VAR1 = 1;
The array is Dumper(16)
$VAR1 = 1;
The array is Dumper(25)
$VAR1 = 1;
The array is Dumper(36)
$VAR1 = 1;
The array is Dumper(49)
$VAR1 = 1;
The array is Dumper(64)
$VAR1 = 1;
The array is Dumper(81)
$VAR1 = 1;
The array is Dumper(100)
$VAR1 = 1;


So I'm assuming that the repeated

$VAR1 = 1;


is the count and not the nested array.

The author did indicate that if the count is what I truly want then to rewrite the code like this:

#!/usr/bin/perl -w
use strict;
use Data::Dumper;

for my $i (1..10) {
my @count;
my @array = somefunc($i);
print "The array is Dumper(@array)\n";
$count[$i] = scalar @array;
print Dumper($count[$i]);
}


sub somefunc {
my $a = shift;
return $a * $a;
}


But the documentation didn't tell me how to get the nested array?

UPDATE

Correct me if I am wrong but I rewrote the code to get the nested array:

#!/usr/bin/perl -w
use strict;
use Data::Dumper;
my @count;
my @new_array;

for my $i (1..10) {
#my @count;
my @array = somefunc($i);
push @new_array, [@array];
}


sub somefunc {
my $a = shift;
return $a * $a;
}

print Dumper(\@new_array);


Which printed

$VAR1 = [
[
1
],
[
4
],
[
9
],
[
16
],
[
25
],
[
36
],
[
49
],
[
64
],
[
81
],
[
100
]
];

Answer

In the following statement:

$AoA[$i] = @array;

the @array is referenced in a scalar context, yielding a number of its elements. The context is imposed by LHS, that is $AoA[$i] which is a single element of the @AoA array.

In Perl, there are no array of arrays in a strict sense. These are emulated essentially by either "flatten" arrays or array with references. For the latter, you would need to use take reference operator as in:

$AoA[$i] = \@array;

For the starter, you may find, that Data::Dumper is very handy in examining complex data stuctures such as arrayrefs and hashrefs.