[Techtalk] Perl Frustration
Almut Behrens
almut-behrens at gmx.net
Fri Oct 31 20:19:42 EST 2003
On Thu, Oct 30, 2003 at 06:09:57PM -0800, Kai MacTane wrote:
>
> I want to declare a set of variables inside a loop, and have them be
> accessible to the rest of the program. It's not known until run-time just
> how many of these variables there are, or what their names will be.
> (...)
>
> print "Enter names of some variables (blank to finish)...\n";
> my $thisline;
>
> chomp($thisline = <STDIN>);
> while ($thisline =~/\w/) {
> $foovar = $thisline.'_foo';
> $$foovar = $thisline;
> chomp($thisline = <STDIN>);
> }
On Fri, Oct 31, 2003 at 01:50:28AM -0800, Kai MacTane wrote:
>
> At least one of the script in question is already released (see
> http://www.gothpunk.com/~kmactane/software/mlm-command), and some of the
> variables I'm looking at need to be available as actual variables. Either
> that, or I'll have to do some ugly hacking to keep the script's behavior
> the same. Or else just change the behavior, and the documentation.
>
> I also thought, "Hey, I can just have them all be keys in a hash!" Then I
> looked at the docs again, and realized that wasn't going to do it. I
> essentially need to take some dynamically-input variables (let's say foo,
> bar and wombat), and wind up having $foo_extra, $bar_extra and
> $wombat_extra be available globally by the end of the script.
>
> Is it possible?
the feature you're using here to define new variables at runtime is
named "symbolic references", and those in principle do not work with
my-variables (reason is, among others, that my-vars have no associated
symbol table). So, if you want to "use strict" (which by default does
not allow symbolic refs), I think you basically only have the following
two options:
(1) locally disable strict checking for the symbolic references:
use strict;
print "Enter names of some variables (blank to finish)...\n";
my $thisline;
chomp($thisline = <STDIN>);
while ($thisline =~/\w/) {
no strict 'refs'; # allow symbolic refs for the next two lines
$main::foovar = $thisline.'_foo';
$$main::foovar = $thisline;
use strict 'refs';
chomp($thisline = <STDIN>);
}
this can, btw, also be written somewhat shorter as follows, not
requiring the intermediate variable $foovar
chomp($thisline = <STDIN>);
while ($thisline =~/\w/) {
no strict 'refs';
${"main::${thisline}_foo"} = $thisline;
use strict 'refs';
chomp($thisline = <STDIN>);
}
(2) use eval to define the new variables at runtime:
use strict;
print "Enter names of some variables (blank to finish)...\n";
my $thisline;
chomp($thisline = <STDIN>);
while ($thisline =~/\w/) {
eval "\$main::${thisline}_foo = '$thisline'";
chomp($thisline = <STDIN>);
}
The latter can at times become somewhat tricky on the right hand side
of the assignment you need to eval (quoting issues) -- though in this
particular case you should be fine, as the value of $thisline would
have to be a valid variable name anyway...
Also, note that, in all cases you need to fully qualify the variable
names (i.e. prefix them with "main::", or whatever package they're in),
if you cannot predeclare them.
Cheers,
Almut
More information about the Techtalk
mailing list