Samn has asked for the wisdom of the Perl Monks concerning the following question:

Replies are listed 'Best First'.
Re: Variables in variable names
by hawtin (Prior) on Nov 30, 2002 at 09:16 UTC

    Why not use an array of arrays to represent the board?

    my(@board,$row,$col,$max_row,$max_col); $max_row = $max_col = 7; for($row=0;$row<$max_row;$row++) { $board[$row] = []; for($col=0;$col<$max_col;$col++) { # Fill out a square ${$board[$row]}[$col] = ??; } }

    The extra complexity of dealing with the nested array structures will be more than made up by the simplification of access. Indead the next level would be to create an object to represent the board and have methods for getting and setting individual cells.

    Use pack to convert the numeric column indexes into letters.

Re: Variables in variable names
by Ryszard (Priest) on Nov 30, 2002 at 09:21 UTC
    I dont really think this is a very scalable solution, it will get confusing and unmaintainable over time.

    Chapter 2 in the Advanced Perl Cookbok deals with matricies. To quote 2.2:

    @matrix = ( [1, 2, 3], [4, 5, 6], [7, 8, 9] ); # Change 6, the element at row 1, column 2 to 100 $matrix[1][2] = 100;

    You can also use a hash representation of the same matrix. (quoting 2.2 again)

    $matrix{0}{2} = 100; $matrix{1}{0} = 200; $matrix{2}{1} = 300;

    As you dont need to preinit data structures in perl, you can just add a new cell by doing something like: $matrix{1}{0}{0} = 400;

    Update: I asked something about variable variables one other time here. It lead me to the conclusion it wasnt really a good idea.. :-)

      I agree, using a matrix of some sort makes the most sense in this case. Often (actually almost always), if you find yourself using variables to hold other variable names you're looking a perfectly good data structure in the face without realizing it. Variable names like 'a4' scream MATRIX. Here's another way to represent a matrix in perl:
      $matrix{'a,4'} = 20; $matrix{'b,5'} = 30;
      Like the nested hash solution($matrix{'a'}{2} = 5;), it lets you use non-numeric indices but uses a little less memory. You can loop through it like so:
      for my $x ('a'..'g') { for my $y (1..6) { my $val = $matrix{"$x,$y"}; ... } }
•Re: Variables in variable names
by merlyn (Sage) on Nov 30, 2002 at 14:36 UTC
    In addition to the good comments from the rest of the responses...
    I have 42 scalers, named like $a3, $c7 and $g2
    ... this is always the warning sign.

    If you have a "bunch of variables named similarly", that's a clue that you really have related data, and related data belongs in a data structure. Because, nearly always, when you have related data, you want to iterate through it somehow, and you can't do it when it's all in separate variables like that. Not without introducing messy-to-maintain code, anyway.

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

Re: Variables in variable names
by Courage (Parson) on Nov 30, 2002 at 09:09 UTC
    Syntax for variable interpolation you're searching is simple:
    ${"$letter$number"};
    but this will be a syntax error when use strict; in effect.
    use strict; could be calmed down by using eval:
    my $result = eval "\$$letter$number";

    But most correct way to solve your problem is just use arrays or hashes.

    Best wishes,
    Courage, the Cowardly Dog

      $letter = 'Oops'; $number = ";print 'You have been hacked!';"; my $result = eval "\$$letter$number";

      Eval (and symbolic references) are dangerous - that print could have been rf -rm /*. Just don't do it.... Typo intentional.

      cheers

      tachyon

      s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

        I am absolutely agree with you
        Besides, /perlfaq\d/ warns about huge sequrity holes in such situations.

        But I tried to provide Samn with a syntax he was searching, and after that to advice a better and safer way to solve his task.

        Best wishes,
        Courage, the Cowardly Dog

Re: Variables in variable names
by Aristotle (Chancellor) on Nov 30, 2002 at 19:05 UTC
    You should read Dominus' archived newsposts, part one, two and three on Why it's stupid to 'use a variable as a variable name'.

    Makeshifts last the longest.

Re: Variables in variable names
by dws (Chancellor) on Nov 30, 2002 at 18:03 UTC
    There are good answers to your general question above, but one line jumped out at me: if (($i == 7) | ($i == 14) | ($i == 21) | ($i == 28) | ... ){ The first thing to jump out is the use of a bitwise or instead of a logical or. Correcting that leaves if (($i == 7) || ($i == 14) || ($i == 21) || ($i == 28) || ... ) { which still has a problem: unecessary parenthesis creating single-elements lists, each containing a boolean. Correcting this leaves if ( $i == 7 || $i == 14 || $i == 21 || $i == 28 || ... ) { This is correct, but a cursory glance shows that the intent is determine whether $i is a multiple of 7 (or, said another way, that $i is divisible by 7 without remainder). There's an easy way to express that: if ( $i % 7 == 0 ) { Phrased this way, you can increase the upper bound on your loop safely without having to add another condition to if if statement. Anytime you have to change code in more than one place to increase the range of a loop, a flag should go up.

      if (($i == 7) || ($i == 14) || ($i == 21) || ($i == 28) || ... ) {
      which still has a problem: unecessary parenthesis creating single-elements lists, each containing a boolean.

      This is wrong. Context creates the list not parentheses. Consider the following code. All the print statements are executed.

      my @ar = ( 0); # Could be: @ar = 0; no precedence problem unless ( 0 ) { print "0 is false!\n"; } unless ( (0) ) { print "(0) is false! But a list w/ 1 item is true.\n"; } if ( @ar ) { print "\@ar, non-empty array is true!\n"; } unless ( list_context() ) { print "scalar context!\n"; } sub list_context { return 1 if wantarray; return; }
      ~