2015-12-09 45 views
1

關於一些單元測試,我發現 能夠從預先聲明的哈希中將一組全局變量導入到當前包中。進口後,他們不應該像$main::var1這樣的包名稱,而是簡單地作爲$var1如何將散列中的變量作爲全局變量導入?

我發現,他們只好再與our被預先聲明,但這是不可能的,例如使用eval '$::var1=3; our $var1'只能申報的eval範圍$var1編程做..

最終我發現我可以使用在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;與硬編碼名稱use vars qw($var1 $var2);它工作正常..

+0

那麼您可以更近一點:'$ main :: var1'也可以稱爲'$ :: var1'。 – Axeman

回答

3
use NAME LIST 

幾乎是一樣的

BEGIN { 
    require NAME; 
    import NAME LIST; 
} 

,並開始塊,儘快爲他們被編譯執行。因此,您將空列表傳遞給vars.pm的import

$ perl -E' 
    BEGIN { 
     say "Outer BEGIN"; 
     my @names = "abc"; 
     BEGIN { say "Inner BEGIN <<@names>>"; } 
    } 
' 
Inner BEGIN <<>> 
Outer BEGIN 

修正:

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)); 
} 

這也可以被寫爲如下:

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; 

到聲明變量的關鍵是在一個不同的命名空間比一個來創建它從哪個它將被訪問。因此,您還可以使用以下內容:

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); 
+0

知道爲什麼有必要從另一個命名空間中定義它會很有趣。如果我在'main'中執行它,我必須使用'our',但是如果我從另一個名稱空間執行它,則不需要用'我們''在'主'。這有什麼意義? –

+0

另外我想全局變量不能被別名放入哈希中。所以,如果我稍後在main中更改'$ var1 = 4','$ var1'不應該同時在另一個包中更改..這就是爲什麼我使用'my $ temp = $ test_vars {$ name}'來在每個名稱空間中創建一個新變量。如果我使用'* $ name = \($ test_vars {$ name});'按照你的建議,我會得到一個別名,對吧? –

+0

它是有道理的。否則,'使用Config qw(%Config);'會創建一個你不能使用的散列 – ikegami