perl eval使用包

问题描述:

中声明的未初始化的值任何人都可以向我解释为什么在包中声明的变量不能被eval函数访问,除非它在sub中使用一次?
(perl的v5.16.3 MSWin32-64的多线程的ActiveState)perl eval使用包

套餐:

use strict; 
use warnings; 
package testPackage; 
my $insertVar = "TEST"; 
sub testSub { 
    my $class = shift; 
    my $test = shift; 
    eval '$test="'.$test.'";'; 
    return $test; 
} 
1; 

计划:

use strict ; 
use warnings ; 
use testPackage ; 
my $testVar = q[insertVar = ${insertVar}] ; 
$testVar = testPackage->testSub($testVar) ; 
print "$testVar\n" ; 

结果来执行程序时:

使用的未初始化值$ insertVar在串联(。)或字符串中 at (eval 1)line 1. insertVar =

现在,如果我使用testSub中的变量(例如,打印出来):

use strict; 
use warnings; 
package testPackage; 
my $insertVar = "TEST"; 
sub testSub { 
    my $class = shift; 
    my $test = shift; 
    print $insertVar . "\n"; 
    eval '$test="'.$test.'";'; 
    return $test; 
} 
1; 

然后该程序运行完全一样我打算:

TEST

insertVar = TEST在一个文件中声明

+0

为什么地球上你会''评估一个变量的赋值来设置自己? – TLP

my变量(花括号外)当文件完成执行时(在requireuse返回之前)超出范围。

$insertVar只会在文件完成执行后才会继续存在,如果它被子捕获,并且只有捕获它的子文件才可见。

出于效率的原因,潜艇捕获了尽可能少的变量。如果子没有引用$insertVar,它将不会捕获它。由于您的第一个testSub未参考$insertVar,因此它不捕获它。由于$insertVar在您拨打testSub时已超出范围,因此eval不可用。您应该收到警告Variable "$insertVar" is not available,但由于我未知的原因,它会针对您使用的特定代码发布。

你的第二个testSub参考$insertVar,所以testSub捕获$insertVar并保持它活着。即使$insertVar在您拨打testSub时已超出范围,但eval可用,因为它已被该子捕获。

如果您使用our声明变量,它们将是全局包变量,因此不会超出范围,它们将可用于eval

>perl -wE"use strict; use warnings; { my $x = 'abc'; sub foo { $x } } say foo()" 
abc 

>perl -wE"use strict; use warnings; { my $x = 'abc'; sub foo { eval '$x' } } say foo()" 
Variable "$x" is not available at (eval 1) line 2. 
Use of uninitialized value in say at -e line 1. 


>perl -wE"use strict; use warnings; { our $x = 'abc'; sub foo { eval '$x' } } say foo()" 
abc 
+0

正确的答案可能是显示此人如何访问包变量。这是一个XY问题。 – TLP

+0

@TLP,我做到了,尽管应该使用适当的模板系统。 – ikegami

+0

ikegami,接受并感谢您的明确回答,关于变量如何被sub捕获的部分是我正在寻找的答案。我无法理解这里发生的事情。 TLP,我知道'我们',并且它让问题消失。我更喜欢ikegami的答案,因为他向我解释了一个包中变量的生命周期如何用'my'声明。 – Veltro