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

I am trying to improve my mind and find a more creative solution to a programming problem. I appeal to the Monks for enlightenment.

I am writing an interface between a low-level PIC controlled device and a high-level voice response system. The serial interface to the PIC was easy, and I can get data in and out of the the VR system.

For the purposes of recursion I create a list of "Zones", like this:

@Zonelist = ("@WGLZAL","@WGLZAU","@WGLZBL","@WGLZBU", "@WGLZCL","@WGLZCU","@WGLZDL","@WGLZDU");

This works well enough for a few zones. But I need to expand this significantly. Increasing the length of this definition seems an ugly and inefficent way to do it.

Each array contains three elements, a text name and two boolean values represented as text strings i.e. @WGLZGL = ("WGLZGL","TRUE", "FALSE");.

The Zone names are predictable, named A-P, upper and Lower. The 'WGL' is more-or-less meaningless, serving only to relate the variables together in the mind of the programmer.

It really seems that it should be practical to recurse thru the alphabet and create the Zonelist dynamically. But I haven't figured out an efficient way to do this.

It also seems I should be able to eliminate the text name since it is the same as the array name. I need to be able to use the name as a string value in several places later. Perhaps I need a painless way to extract the array name as a string to use. Here is one example of how it is used.

foreach $zone (@Zonelist) { @cmmd = split(/ /,$zone); print "Updating Flag @cmmd[0] from @cmmd[1]to @cmmd[2]"; }

Can the Perl Monks enlighten me?

Nathan

Replies are listed 'Best First'.
Re: Novice flails arrays
by kvale (Monsignor) on Mar 26, 2004 at 21:44 UTC
    I'd eliminate the WGL; it is redundant. Perhaps a hash is what you are looking for?
    my %zone; foreach my $name (AA..ZZ) { $zone{$name} = [ qw|FALSE FALSE| ]; }
    Note that I did not include the name in the array; it is redundant with the key. To access the boolean flags associated with name 'fo', use
    my ($flag0, $flag1) = @{ $zone{fo} }; # or my $flag0 = $zone{fo}[0]; my $flag1 = $zone{fo}[1];

    -Mark

      Maybe eliminating WGL is a good idea. It actually signifies that the variable in question is tied to the PIC device, which is made by WGL Designs. Z indicates the variable is related to a specific Zone. So they do have meaning. But perhaps it is not necessary. It does contribute to readability in the larger program as the reader knows what any variable named WGL refers to. There are many other variables that refer to other parts of the system.

      Thanks, I will study your examples.

      Nathan

Re: Novice flails arrays
by dragonchild (Archbishop) on Mar 27, 2004 at 01:53 UTC
    This sounds like configuration data. Configuration data doesn't belong in a program. It belongs in a configuration file. I personally like Apache::ConfigFormat, but there are many other configuration schemes on CPAN.

    Additionally, if it's just a bunch of data that needs generated, I like HTML::Template for creating bunches of similar files. I use it for creating DDL to make auditing triggers for SQL tables. Of course, there's Text::Template and about another hundred templating schemes. (There's almost as many templating systems as there are configfile systems, and both are the most popular module types on CPAN.)

    ------
    We are the carpenters and bricklayers of the Information Age.

    Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

Re: Novice flails arrays
by davido (Cardinal) on Mar 27, 2004 at 06:53 UTC
    @Zonelist = ("@WGLZAL","@WGLZAU","@WGLZBL","@WGLZBU", "@WGLZCL","@WGLZCU","@WGLZDL","@WGLZDU");

    I really don't like lists of named arrays being used when a hash is a more convenient solution.

    my %zonelist; foreach my $zone ('AA'..'ZZ') { my $key = 'WGLZ' . $zone; $zonelist{$key} = [ 'TRUE', 'FALSE' ]; }

    or...

    my %zonelist = map { 'WGLZ' . $_, ['TRUE','FALSE'] } ( 'AA' .. 'ZZ' );

    Of course using an anonymous array holding two strings, "TRUE" and "FALSE" is more of a memory hog than the same anonymous array holding two numeric values: 1, and 0. And even that's more of a hog than a simple scalar value, containing the string "10". ...and that's more of a memory hog than a simple scalar value containing the numeric value of 0, 1, 2, or 3.

    In other words, you could replace the anonymous array holding "TRUE" and "FALSE" with a numeric representation like this:

    NUMERIC | VAL1 | VAL2 --------+-------+--------- 0 | FALSE | FALSE --------+-------+--------- 1 | FALSE | TRUE --------+-------+--------- 2 | TRUE | FALSE --------+-------+--------- 3 | TRUE | TRUE --------^-------^---------

    ...and that is starting to look a lot like a job for vec.


    Dave