Perl multidimensional arrays with "use strict"

F

Franck

Hi!

Little problem there. Can someone tell me what's the problem with
this? The first test below works while the second doesn't. I have to
use strict so I need to know why it doesn't work and what I have to do
to fix the problem in the second test. It complains when I put items
in the second dimension of the array..."Can't use string ("group 0")
as an ARRAY ref while "strict refs" in use at test.pl line 18."

Thx a lot!
Franck

#################################################
#FIRST TEST
$i = 0;
$j = 0;
$k = 0;

@data = ();

for ($i=0; $i<=3; $i++){
$data[$i] = "group $i";

for ($j=0; $j<=3; $j++){
$temp1 = $j+$i+10;
$data[$i][$j] = "user $temp1";

for ($k=0; $k<=3; $k++){
$temp2 = $k+100;
$data[$i][$j][$k] = " $temp2";
}
}
}

for ($i=0; $i<=3; $i++){
print "\n\n$data[$i] own: ";
for ($j=0; $j<=3; $j++){
print "\n $data[$i][$j] who have privilege ";
for ($k=0; $k<=3; $k++){
print "$data[$i][$j][$k],";
}
}
}
#################################################

#################################################
#SECOND TEST
use strict;
use warnings;


my $i = 0;
my $j = 0;
my $k = 0;

@::data = ();
my $temp1;
my $temp2;

for ($i=0; $i<=3; $i++){
$::data[$i] = "group $i";

for ($j=0; $j<=3; $j++){
$temp1 = $j+$i+10;
$::data[$i][$j] = "user $temp1";

for ($k=0; $k<=3; $k++){
$temp2 = $k+100;
$::data[$i][$j][$k] = " $temp2";
}
}
}

for ($i=0; $i<=3; $i++){
print "\n\n$::data[$i] own: ";
for ($j=0; $j<=3; $j++){
print "\n $::data[$i][$j] who have privilege ";
for ($k=0; $k<=3; $k++){
print "$::data[$i][$j][$k],";
}
}
}
#################################################
 
P

Paul Lalli

Hi!

Little problem there. Can someone tell me what's the problem with
this? The first test below works while the second doesn't. I have to
use strict so I need to know why it doesn't work and what I have to do
to fix the problem in the second test. It complains when I put items
in the second dimension of the array..."Can't use string ("group 0")
as an ARRAY ref while "strict refs" in use at test.pl line 18."

Thx a lot!
Franck

#################################################
#FIRST TEST
#################################################
#SECOND TEST
use strict;
use warnings;


my $i = 0;
my $j = 0;
my $k = 0;

@::data = ();

Why are you using a global variable? This isn't 'wrong' per say, but it
is unusual. You usually want a lexical variable, especially with
strictures enabled:

my @data;
my $temp1;
my $temp2;

for ($i=0; $i<=3; $i++){
$::data[$i] = "group $i";

Okay, here you are filling the array @data with text strings. Position 0
contains "group 0", position 1 contains "group 1", etc.
for ($j=0; $j<=3; $j++){
$temp1 = $j+$i+10;
$::data[$i][$j] = "user $temp1";

Here you're suddenly deciding that @data no longer contains text strings,
and instead now contains references to arrays. Why? The error you're
rightly getting is telling you that $data[$i] contains the string "group
$i", which you are attempting to convert to an array reference.

for ($k=0; $k<=3; $k++){
$temp2 = $k+100;
$::data[$i][$j][$k] = " $temp2";

Same problem. Assuming the above worked, $data[$i][$j] would contain the
text string "user 10" (for example). Now you're trying to use that string
as an array reference.

}
}
}

for ($i=0; $i<=3; $i++){
print "\n\n$::data[$i] own: ";
for ($j=0; $j<=3; $j++){
print "\n $::data[$i][$j] who have privilege ";
for ($k=0; $k<=3; $k++){
print "$::data[$i][$j][$k],";
}
}
}
#################################################

I think it would be good for you to define what your goal is, rather than
defining what you think you have to do to obtain that goal. Using
symbolic references (which is the official term for what you're trying to
do here) is A Bad Idea, which is why it's disabled by use strict;. So,
what is it you *want* to do? Once you tell us that, we can help you
figure out the correct way of obtaining that goal.

Paul Lalli
 
E

Eric Bohlman

(e-mail address removed) (Franck) wrote in
Little problem there. Can someone tell me what's the problem with
this? The first test below works while the second doesn't. I have to
use strict so I need to know why it doesn't work and what I have to do
to fix the problem in the second test. It complains when I put items
in the second dimension of the array..."Can't use string ("group 0")
as an ARRAY ref while "strict refs" in use at test.pl line 18."

Because you've inadvertently created a symbolic reference instead of an
array of array references ("AoA") (which is how a multidimensional array is
implemented.
#FIRST TEST
$i = 0;
$j = 0;
$k = 0;

@data = ();

for ($i=0; $i<=3; $i++){
$data[$i] = "group $i";

First time around, $data[0] eq 'group 0'
for ($j=0; $j<=3; $j++){
$temp1 = $j+$i+10;
$data[$i][$j] = "user $temp1";

And this assignment actually works out to

${'group 0'}[0] = "user 10";

because it's using $data[0] as a symref, which is disallowed under strict.

I suspect you really want a multidimensional *hash* ("HoH") here rather
than an array. Reading perlreftut, perllol, and perldsc should set you in
the right direction.
 
T

thundergnat

Franck said:
Hi!

Little problem there. Can someone tell me what's the problem with
this? The first test below works while the second doesn't. I have to
use strict so I need to know why it doesn't work and what I have to do
to fix the problem in the second test. It complains when I put items
in the second dimension of the array..."Can't use string ("group 0")
as an ARRAY ref while "strict refs" in use at test.pl line 18."

Thx a lot!
Franck

Well, very much like it is saying, you are trying to use a string as an
array ref. When you create lists of lists: $::data[$i][$j], the $i array
holds references to the arrays indexed by the $j variable. You can't
just arbitrarily assign strings to them, they are already in use as
array references.


#################################################
#SECOND TEST
use strict;
use warnings;


my $i = 0;
my $j = 0;
my $k = 0;

@::data = ();
my $temp1;
my $temp2;

for ($i=0; $i<=3; $i++){
$::data[$i] = "group $i";

for ($j=0; $j<=3; $j++){
$temp1 = $j+$i+10;
$::data[$i][$j] = "user $temp1";

for ($k=0; $k<=3; $k++){
$temp2 = $k+100;
$::data[$i][$j][$k] = " $temp2";
}
}
}

for ($i=0; $i<=3; $i++){
print "\n\n$::data[$i] own: ";
for ($j=0; $j<=3; $j++){
print "\n $::data[$i][$j] who have privilege ";
for ($k=0; $k<=3; $k++){
print "$::data[$i][$j][$k],";
}
}
}
#################################################

I would rewrite this this way:

Since you are just using the indicies to calculate the various
parameters, you can just perform the calculations when you need them,
rather than precalculating them and storing them. Declare your variables
for the smallest scope necessary. Avoid using unnecessary temp
variables. I'm not sure why you were using a package variable (@::data),
it's not really wrong if you need the varible to be global, but you
should probably avoid it unless you definitely need the global scope.

You may be served better by a different data structure. Without knowing
more about what kinds of information you are storing, how much of it
there will be and how you need to retrieve it, it is difficult to say.

You might want to look at the perl docs about lists of lists.

perldoc perllol - or -

http://www.perl.com/doc/manual/html/pod/perllol.html




(Anyway, I doubt if this is what you really /wanted/, but it is
essentially what you were /trying/ to do.)


use strict;
use warnings;

my @data = ();

for my $i (0..3){
for my $j (0..3){
for my $k (0..3){
$data[$i][$j][$k] = $k+100;
}
}
}

for my $i (0..3){
print "\n\ngroup $i own: ";
for my $j (0..3){
print "\n user ",$j+$i+10,' who have privilege';
for my $k (0..3){
print ' ',$k+100,",";
}
}
}
 
T

thundergnat

thundergnat said:
use strict;
use warnings;

my @data = ();

for my $i (0..3){
for my $j (0..3){
for my $k (0..3){
$data[$i][$j][$k] = $k+100;
}
}
}

for my $i (0..3){
print "\n\ngroup $i own: ";
for my $j (0..3){
print "\n user ",$j+$i+10,' who have privilege';
for my $k (0..3){
print ' ',$k+100,",";
}
}
}

Ummm. Make that:

use strict;
use warnings;

my @data = ();

for my $i (0..3){
for my $j (0..3){
for my $k (0..3){
$data[$i][$j][$k] = $k+100;
}
}
}

for my $i (0..3){
print "\n\ngroup $i own: ";
for my $j (0..3){
print "\n user ",$j+$i+10,' who have privilege';
for my $k (0..3){
print ' ',$data[$i][$j][$k],",";
}
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top