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

I'm writing a very simple tic-tac-toe program that will learn from bad lines of play. As such, I want a hash to be named for each line it finds to be poor, so I figured I'd name the hash the actual bad sequence.

For example, if 1-2-5-9-8 is the bad line, then I want to name the hash %12598. Can I do this??

Replies are listed 'Best First'.
Re: multidimensional arrays
by btrott (Parson) on Apr 03, 2000 at 11:15 UTC
    A variable name must start with a letter or an underscore. From perldata:
    The rest of the name tells you the particular value to which it refers. Most often, it consists of a single identifier, that is, a string beginning with a letter or underscore, and containing letters, underscores, and digits.
    However, a hash *key* can quite well consist only of digits; so as you allude to in the title, what you probably need here is a multidimensional data structure. I don't know what you're planning to store in addition to the bad sequence... presumably something for which you needed a hash in the first place. But anyway:
    my %bad = ( '12598' => {}, # data about bad sequence '19203' => {}, # data about other bad sequence )
    and so on. Each bad sequence string maps in the hash to an anonymous hash that you can use just as you planned to use your original hash, %12598. Instead of saying
    $12598{'foo'} = 'bar'; # wrong and illegal
    now you'd say
    $bad{'12598'}{'foo'} = 'bar';
    Make sense?
Re: multidimensional arrays
by stephen (Priest) on Apr 03, 2000 at 22:45 UTC
    Another idea would be to have a hash for every move. In other words, instead of:
    my %bad = ( '12598' => {}, # data about bad sequence '19203' => {}, # data about other bad sequence )
    you could have something like:
    $bad->{1}{2}{5}{9}{8} = 0;
    That way, you could keep a pointer to the current move history just by looking up each move as it's made, and keeping a variable with the last lookup value in it. (Of course, that won't work if you're implementing this as a CGI, but...) Then, the program can just check to see if 8 would be a bad move by seeing if $move->{8} is equal to zero.

    For a full discussion and mini-rant on the subject of having variables named at runtime, see Mark-Jason Dominus' article on the subject here: http://www.plover.com/~mjd/perl/varvarname.html

    stephen

RE: multidimensional arrays
by chromatic (Archbishop) on Apr 03, 2000 at 22:02 UTC
    A hash of hashes is the best idea here. Otherwise, you'd probably have to use symbolic references (which is a bad idea in this case).

    One trick novice programmers all seem to try at least once (not addressing nascent here, but taking the opportunity to step up on a soapbox) is creating variable and object names like Car1, Car2, and Car3. They go through manipulations like: ${"Car$i"}->{color} = "blue"; This can introduce subtle bugs as you're depending on a lot of things being correct to get and to set your variable. (In my example, use an array: @cars.) Now you have only one place to go to get or set your car properties. You know the index for first element and can get the index for the last element with ease. Best of all, if you use strict and -w, Perl will catch any typos for you.