Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

How can I turn a string into a variable name?

by mnooning (Sexton)
on Jan 09, 2010 at 19:05 UTC ( #816523=perlquestion: print w/ replies, xml ) Need Help??
mnooning has asked for the wisdom of the Perl Monks concerning the following question:

I want to check if more than one of the many GetOptions options were used, and I want to know which ones were used. More than one is not allowed. For a quick check, I tried with only three options. In the code below, which does NOT work, only the "two" should match.
use strict; my $one = 0; my $two = 1; my $three = 0; my @strings = qw (one two three); my @optionsToCheck = ($one, $two, $three); foreach my $string (@strings) { print "Option $string was used\n" if ( ${"$string"} ); }
I tried different variations, but could not seem to get it. I could use a key/value hash, but that seems overkill. Besides, if I added or took away options, I'd have to remember to change the hash, too. I suspect Perl has a simple answer, but I cannot see it.

Thanks

Comment on How can I turn a string into a variable name?
Download Code
Re: How can I turn a string into a variable name?
by ikegami (Pope) on Jan 09, 2010 at 19:13 UTC

    Don't.

    GetOptions( '--one' => \$one, '--two' => \$two, '--three' => \$three, ); die "Only one of options --one, --two and --three are allowed\n" if ( grep defined, $one, $two, $three ) > 1;
    or
    GetOptions( '--one' => \$opts{one}, '--two' => \$opts{two}, '--three' => \$opts{tree}, ); die "Only one of options @{[ sort keys %opts ]} are allowed\n" if ( grep defined, values(%opts) ) > 1;

    Update: Updated since I hadn't properly read the question initially.

Re: How can I turn a string into a variable name?
by chromatic (Archbishop) on Jan 09, 2010 at 19:15 UTC

    If you really cannot use a hash (and that's easily the best way to do this), install PadWalker and use my $lexicals = peek_my(0); to get a hash reference which you can use to manipulate all lexical variables bound to the current scope.

    (If manipulating Perl 5 internals from pure Perl still seems less overkill than using a hash, consider that PadWalker can read from and write to and even create lexicals in other scopes, ignoring encapsulation.)

      I can use a hash. It looks like that is what I will do. I was just hoping for a slicker way. Thanks
Re: How can I turn a string into a variable name?
by almut (Canon) on Jan 09, 2010 at 19:27 UTC

    In theory, you could write

    print "Option $string was used\n" if ( eval "\$$string" );

    But, as already said, don't.  eval in this context is definitely worse than using a hash, in almost every regard.

      Why use eval to do
      if do { no strict 'refs'; $$string };
        Why use eval

        ...because the OP used lexical variables.  Symbolic references ($$string) only work with package variables.

Re: How can I turn a string into a variable name?
by GrandFather (Cardinal) on Jan 09, 2010 at 21:58 UTC

    Where do the 'options' come from? If they are from the command line use Getopt::Long. If they are derived internally (perhaps through a GUI or command line interface) then you could:

    use strict; use warnings; my %options = map {$_ => 0} qw(one two three); $options{two} = 1; # Set in some unspecified place for my $option (grep {$options{$_}} keys %options) { print "Option '$option' was used\n"; }

    Prints:

    Option 'two' was used

    True laziness is hard work

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (17)
As of 2014-07-31 13:12 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (248 votes), past polls