Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

understanding data structures in perl

Tags:

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
      ]
    ];
like image 805
BioRod Avatar asked Nov 26 '25 10:11

BioRod


2 Answers

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.

like image 154
Grzegorz Szpetkowski Avatar answered Nov 28 '25 15:11

Grzegorz Szpetkowski


Perl is polymorphic, which means that it deals with different data types transparently, and makes what is usually a pretty good guess on how to deal with something. This makes the programmer's work much easier because it is not strongly typed like other languages.

So for example if $i is the number 4, you can do this:

print $i + 1;

and you will see a 5 - pretty logical, right?

and if you do this:

print "I am " , $i , " years old";

You will see "I am 4 years old" - in this case perl says "you are operating in list context, so I will treat $i as a string. No need to convert the number into a string as many other languages insist.

So when you assign

$AoA[$i] = @array;

The way it treats this depends on the context. In scalar context, it will set $AoA[$i] to be the length of the array.

For more information about scalar vs list context, read this answer:

http://perl.plover.com/context.html

like image 25
Mikkel Avatar answered Nov 28 '25 16:11

Mikkel



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!