Perl multidimensional arrays with "use strict"

Discussion in 'Perl Misc' started by Franck, Jun 15, 2004.

  1. Franck

    Franck Guest

    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],";
    }
    }
    }
    #################################################
     
    Franck, Jun 15, 2004
    #1
    1. Advertising

  2. Franck

    Paul Lalli Guest

    On Tue, 15 Jun 2004, Franck wrote:

    > 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

    <code without strict snipped>

    > #################################################
    > #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
     
    Paul Lalli, Jun 15, 2004
    #2
    1. Advertising

  3. Franck

    Eric Bohlman Guest

    (Franck) wrote in
    news::

    > 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.
     
    Eric Bohlman, Jun 15, 2004
    #3
  4. Franck

    thundergnat Guest

    Franck wrote:
    > 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,",";
    }
    }
    }
     
    thundergnat, Jun 15, 2004
    #4
  5. Franck

    thundergnat Guest

    thundergnat wrote:

    >
    > 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],",";
    }
    }
    }
     
    thundergnat, Jun 15, 2004
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. d[ - - ]b

    Multidimensional arrays? anything else?

    d[ - - ]b, May 18, 2004, in forum: ASP .Net
    Replies:
    2
    Views:
    1,674
    AlexS
    May 18, 2004
  2. Philipp
    Replies:
    21
    Views:
    1,130
    Philipp
    Jan 20, 2009
  3. Francesco
    Replies:
    2
    Views:
    1,111
    Francesco
    Nov 6, 2009
  4. Ben Edwards
    Replies:
    2
    Views:
    92
    James Edward Gray II
    Jul 13, 2007
  5. Tintin
    Replies:
    4
    Views:
    101
    Tintin
    Jan 29, 2008
Loading...

Share This Page