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

Hard to explain what happens, but I'll try my best. I have some variables such as $total_george_money, $max_george_budget, $total_lindsay_money, $max_lindsay_budget. Since the script gets very long, I'm trying to make it more dynamic and I have no idea how to put these names: george, lindsay and so on inside the $total_...._money variable name. Any ideas?

Replies are listed 'Best First'.
Re: Dynamic variables
by sschneid (Deacon) on Jul 22, 2004 at 16:35 UTC
    Maybe a hash of hashes?
    my %hash = ( george => { maxbudget => '1200', totalmoney => '2400' }, lindsay => { madbudget => '2400', totalmoney => '5600' } );

    -s.
Re: Dynamic variables
by eric256 (Parson) on Jul 22, 2004 at 16:36 UTC

    You are looking for hashes.

    my $max = {}; $max->{george}->{money} = 100; $max->{george}->{budget} = 100; my $person = "lindsay"; $max->{$person}->{money} = 1500; $max->{$person}->{budget} = 2000; for ("george","lindsay") { print "$_ 's money= " . $max->{$_}->{money} . "\n"; }

    ___________
    Eric Hodges

      I must say, while your advice (to use a hash) seems perfectly sensible, I'm sort of confused about why you used a hashref instead of a plain hash. Also, you included some superfluous punctuation between the nested subscripts in your assignments. Do you just like typing the arrow operator that much? :-)

      Here's how I'd have done it. Not all that different, but sometimes small things can make a difference:

      my %max; $max{george}{money} = 100; $max{george}{budget} = 100; my $person = "lindsay"; $max{$person}{money} = 1500; $max{$person}{budget} = 2000; for ("george","lindsay") { printf "%s's money= %d\n", $_, $max{$_}{money}; }

        I prefer a hashref for many reasons but mostly just because its what i've always used and i came from a VB + C background where -> doesn't seem like all that much to type. It makes it clear to me whats going on and I don't mind the two extra key strokes. BTW is there a reason to use a regular hash instead of a ref? The -> also makes it feel more like a pointer so it flows with my way of thinking better. I'm not sure there are any real advantages speed or functionality wise to pick between using it or not though.


        ___________
        Eric Hodges
      Thank you. I think i got it now.
Re: Dynamic variables
by davido (Cardinal) on Jul 23, 2004 at 05:24 UTC

    It hasn't yet been said in this thread, and should have been: Don't try to do what you're trying to do.

    The advice to use a hash is the obligatory right answer under most situations where you might be tempted to create variable names on the fly, at runtime.

    What you're trying to do, in your specific case, is create a symbolic reference, or a soft reference. A symbolic (or soft) reference, in Perl, is where you use some value (computed or stored in a variable) to indicate the name of a variable. Perl lets you do this (if you use the right syntax, and if you don't use strict;). Don't be tempted to use this "feature" of Perl, until you're intimately familiar with the reasons why you shouldn't use this feature.

    Almost always, it's better to use a hash, or hard references, or some combination of the two. The fact is that the package global namespace really is just a glorified hash anyway. If that's good enough for perl (the executable), it's probably good enough for you too... but don't muck around with your program's package global namespace hash (Ugh, what a mess that would be!)... use your own hash to hold these dynamic names. Treating your package global namespace like a symbolic scratchpad is sooner or later (probably sooner) cause you a lot of headaches in the form of hard-to-find bugs, latent bugs, variable collisions, and so on. As merlyn once said, "If you're just here to watch the play, stay out from behind the curtain." (that's from memory, so it may be a little less than a direct quote)


    Dave

Re: Dynamic variables
by periapt (Hermit) on Jul 23, 2004 at 12:37 UTC
    The data structure that you use depends, in part, on what you are trying to accomplish. However, from your writeup, it seems that you have several different users/entities with basically the same information describing them. I assume the program then performs a set of standard operations on the data about these users/entitites one user at a time.

    Given that, I would store the info about these users in a HoH or AoH. This data structure gives you the ability to access data about the users dynamically. Once a user is determined, you can store a reference to that users data structure into a generic hash and use that reference throughout the rest of the program. That way you don't have to try and code references to specific users elsewhere in the program.

    my %users = ( george => { total_money => "42", max_money => "100" }, lindsay => { total_money => "125", max_money => "1000" }, }; my $userref = \$users{$userid}; # the rest of the program accesses $userref specifically ...

    PJ
    unspoken but ever present -- use strict; use warnings; use diagnostics; (if needed)