Ahmad Bilal Ahmad Bilal - 3 months ago 8
Perl Question

How can I combine two strings and treat the result as the name of a variable?

How can I combine two strings and treat the result as the name of a variable?

I tried this:

my $container0 = "voila";
my $container1 = "ssss";
my $container2 = "swat";

my $container3 = int rand 2;

my $ans = '$container'."$container3";

print "$ans";


But it prints:

$container2


I want to print:

swat


(the value of the variable
$container2
). How can I do this?

Answer

First off - as the comments say read this: http://perl.plover.com/varvarname.html

The way to do this is with a hash.

my %stuff;

$stuff{'container0'} = "voila";
$stuff{'container1'} = "ssss"; 
$stuff{'container2'} = "swat";

my $value = int rand 3;

my $ans = $stuff{'container'.$value};
print $ans,"\n";

(Needs to be 3 - int rand 2 will only ever give you 1 or 0).

However, that's perhaps a bit more complicated than you need.

Instead:

my @container = qw ( voila ssss swat );
print $container[rand @container],"\n"; 

For the sake of completeness - here is how you can do it:

YOU SHOULD NEVER EVER DO THIS, IT IS A TERRIBLE IDEA! IT WILL BREAK YOUR CODE IN ALL SORTS OF OBSCURE WAYS AND IS ENTIRELY REDUNDANT WHEN YOU HAVE HASHES

$container0 = "voila";
$container1 = "ssss"; 
$container2 = "swat"; 

$container3 = int rand 3; 

$ans = 'container'."$container3"; 

print $$ans,"\n"; 

This will give you errors under strict and warnings.

Can't use string ("container1") as a SCALAR ref while "strict refs" in use

There is a good reason that it does this. I seriously, cannot re-iterate enough how terrible an idea it is to do this when you've perfectly good hashes available. There are all sorts of incredibly funky ways that clobbering random variables in your code can go disastrously wrong. Seriously - read the link above. It has some lovely examples. The best being if you accidentally tamper with some of the special variables, such as $* or $/ and screw up every regular expression or filehandle in the rest of your program - you'll be looking in the wrong place for the source of the error.

Edit: To follow on from a comment - you cannot use my if you do this - you need to use our. The easiest way to understand why, is just imagine that my renames a variable to a function unique name, and 'hides' it from the rest of the package. Because the symbolic ref evaluates at run time - perl can't pre-prepare when it's doing it's compilation and validation phases, so cannot 'see' the lexically scoped variable when it's running.

Using our would declare the variable in a broader scope (e.g. effectively global). So like this: (But it's still nasty)

use strict;
use warnings;

no strict "refs"; 

our $container0 = "voila";
our $container1 = "ssss"; 
our $container2 = "swat"; 

my $container3 = int rand 3; 

my $ans = 'container'."$container3"; 

print $$ans,"\n"; 

Also refer to the FAQ for some more reasons it's not a good idea:

http://perldoc.perl.org/perlfaq7.html#How-can-I-use-a-variable-as-a-variable-name%3f