Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Dynamically Building Variable Names

by willyyam (Priest)
on Apr 22, 2005 at 16:59 UTC ( #450488=perlquestion: print w/ replies, xml ) Need Help??
willyyam has asked for the wisdom of the Perl Monks concerning the following question:

What I am trying to do may be stupid/daft/wrong-headed; any alternate methods would be appreciated.

I wanted to put a variable name together dynamically inside a sub, based on the arguments of that sub. For instance, if the first argument is "example" and the second is "other", I wanted to define a variable called $exampleother1, or $exampleother2. I can concatenate variables and strings, but I don't know how to concatenate a string and then make it a variable name.

Because this seems hard/strange I suspect that it is also idiotic, but I think I'm better off asking for the wisdom (and tolerance) of the monks then to sit in ignorance.

Update: Yep, stupid, daft and wrong-headed. Using a data structure to capture my cases makes more sense then trying to build case-specific variables. I should stop asking questions and just re-read the Llama book each time I find something difficult. Thanks for the suggestions, guidance and references.

Comment on Dynamically Building Variable Names
Re: Dynamically Building Variable Names
by Fletch (Chancellor) on Apr 22, 2005 at 17:03 UTC

    No, you probably don't want that. You want a real data structure, possibly a hash of hashes of arrays by your description.

    my $data = { example => { other => [ ], } }; $data->{example}->{other}->[0] = "wuzzle";

    See perldoc perlreftut and perldoc perldsc.

      Or, just to keep it simple, and more like what was requested originally (as there may be something else that we don't know about, that would have problems if it were a deep structure), you can use a flat hash:

      my %data; $data{'exampleother1'} = 'something'; $data{'exampleother2'} = 'something else'; $data{$var1.$var2.$number} = $value; # or using a hashref my $data; $data->{'exampleother1'} = 'something'; $data->{'exampleother2'} = 'something else'; $data->{$var1.$var2.$number} = $value;

      The deeper structure has advantages if you might have values for ($var1.$var2) that collide. (if those should be two discrete values, then use a hash of hashes or some other complex structure. If they should be the same value, then just use a single dimensional hash).

Re: Dynamically Building Variable Names
by samizdat (Vicar) on Apr 22, 2005 at 17:12 UTC
    It should be quite straighforward:
    sub foo { my $basename = $_[0] . $_[1]; my $addon = '0'; while (defined($(my $goodname = "$basename$addon")) { $addon++; } my $$goodname = $_[2]; return $goodname; }
    untested, but
    $name = foo('example','other', 49); print $$name . "\n";
    should print 49 and put 49 in variable $exampleother0

    Update: I use symbolic variables quite a bit for reusable code, but I agree with Fletch that you should learn to use data structures first.

    2 made the code function correctly... :D
      No. Don't do that. You really don't want to do that. Really not. Don't let your data become code, or code become data. That's the way to harder bugs to debug, or potential security holes.

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

Re: Dynamically Building Variable Names
by polettix (Vicar) on Apr 22, 2005 at 17:17 UTC
    I agree with Fletch that you probably don't want it.

    I can see some vague utility if you want to access global variables. In this case, you can use a plain hash to get a quick hack that works even with strict and warnings turned on:

    #!/usr/bin/perl use strict; # Use good practices use warnings; my %globals = (barbaz => "something here"); foo("bar", "baz"); sub foo { my $name = join('', @_); # Build varname print $globals{$name}, "\n"; # use it at will.... }
    If you want to go the dark-side way (but remember that it's difficult to get back!), you have to indirect the variable name you're building:
    #!/usr/bin/perl $barbaz = "something here"; foo("bar", "baz"); sub foo { $name = join('', @_); # Build varname print $$name, "\n"; # use it AT YOUR RISK! }
    But, at the risk of repeating myself and Fletch, you don't want to do that.

    Flavio (perl -e 'print(scalar(reverse("\nti.xittelop\@oivalf")))')

    Don't fool yourself.
      Just to hammer the point home even more - your second example is identical to
      #!/usr/bin/perl $barbaz = "something here"; foo("bar", "baz"); sub foo { $name = join('', @_); # Build varname print $main::{$name}, "\n"; }

      In other words, you're using a hash - the package's symbol table. However, if you don't want to clobber something, use your own hash.

Re: Dynamically Building Variable Names
by Roy Johnson (Monsignor) on Apr 22, 2005 at 17:50 UTC
    You're certainly not the first person to want to do this. Great answers have been given here, but in my opinion you should check out the best answer that has been given in the past. If you read the links, you will be truly enlightened on this matter.

    Caution: Contents may have been coded under pressure.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://450488]
Approved by johnnywang
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (11)
As of 2014-09-16 19:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (44 votes), past polls