如何从散列中导入变量作为全局变量?

时间:2015-12-09 23:32:07

标签: perl

关于一些单元测试,我发现它会很好 能够从预先声明的哈希中将一组全局变量导入当前包中。导入后,它们不必像$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;,它就可以了。

1 个答案:

答案 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 );