关于一些单元测试,我发现它会很好
能够从预先声明的哈希中将一组全局变量导入当前包中。导入后,它们不必像$main::var1
这样的包名称限定,而只需要$var1
。
我发现他们必须使用our
预先声明,但是这不可能以编程方式执行,例如使用eval '$::var1=3; our $var1'
只会在{{1}范围内声明$var1
}} ..
最终我发现我可以使用eval
pragma:
vars
但这会产生错误:
use feature qw(say);
use strict;
use warnings;
BEGIN {
my %test_vars = ( var1 => 3, var2 => 1 );
my @names;
for my $key (keys %test_vars) {
my $temp = $test_vars{$key};
no strict 'refs';
*{"main\::$key"} = \$temp;
push @names, "\$$key";
}
use vars @names;
}
#our $var1;
say $var1;
如果我用硬编码的名称Variable "$var1" is not imported at ./p.pl line 22.
Global symbol "$var1" requires explicit package name at ./p.pl line 22.
Execution of ./p.pl aborted due to compilation errors.
替换use vars @names;
,它就可以了。
答案 0 :(得分:3)
use NAME LIST
is virtually the same as
BEGIN {
require NAME;
import NAME LIST;
}
and BEGIN blocks are executed as soon as they are compiled. As such, you're passing an empty list to vars.pm's import
.
$ perl -E'
BEGIN {
say "Outer BEGIN";
my @names = "abc";
BEGIN { say "Inner BEGIN <<@names>>"; }
}
'
Inner BEGIN <<>>
Outer BEGIN
Fix:
use vars qw( );
BEGIN {
my %test_vars = ( var1 => 3, var2 => 1 );
for my $name (keys(%test_vars)) {
no strict qw( refs );
*$name = \( $test_vars{$name} );
}
vars->import(map "\$$_", keys(%test_vars));
}
This could also be written as follows:
BEGIN {
package AppVars;
use Export qw( import );
my %test_vars = ( var1 => 3, var2 => 1 );
our @EXPORT = map "\$$_", keys(%test_vars);
for my $name (keys(%test_vars)) {
no strict qw( refs );
*$name = \( $test_vars{$name} );
}
$INC{"AppVars.pm"} = 1;
}
use AppVars;
The key to declaring a variable is to create it in a different namespace than the one from which it will be accessed. As such, you could also use the following:
BEGIN {
package initialized_vars;
sub import {
shift;
my %hash = @_;
my $pkg = caller;
for my $name (keys(%hash)) {
no strict qw( refs );
*{$pkg.'::'.$name} = \( $hash{$name} );
}
}
$INC{"initialized_vars.pm"} = 1;
}
use initialized_vars ( var1 => 3, var2 => 1 );