perl eval 使用包中声明的未初始化值
perl eval Use of uninitialized value declared in package
任何人都可以向我解释为什么在包中声明的变量不能被 eval 函数访问,除非它在 sub 中使用一次吗?
(perl v5.16.3 MSWin32-x64-多线程 ActiveState)
包裹:
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" ;
执行程序时的结果:
Use of uninitialized value $insertVar in concatenation (.) or string
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
my
文件中声明的变量(在卷曲之外)在文件完成执行时超出范围(在 require
和 use
return 之前)。
$insertVar
只有在文件被sub捕获后才会继续存在,并且只有捕获它的sub可见。
出于效率原因,潜艇捕获尽可能少的变量。如果 sub 没有引用 $insertVar
,它就不会捕获它。由于您的第一个 testSub
没有引用 $insertVar
,因此它不会捕获它。由于在您调用 testSub
时 $insertVar
已经超出范围,因此它对 eval
不可用。您应该收到警告 Variable "$insertVar" is not available
,但出于我不知道的原因,它是针对您使用的特定代码发出的。
您的第二个 testSub
引用 $insertVar
,因此 testSub
捕获 $insertVar
并使其保持活动状态。尽管在您调用 testSub
时 $insertVar
已经超出范围,但由于它被子程序捕获,因此 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
任何人都可以向我解释为什么在包中声明的变量不能被 eval 函数访问,除非它在 sub 中使用一次吗?
(perl v5.16.3 MSWin32-x64-多线程 ActiveState)
包裹:
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" ;
执行程序时的结果:
Use of uninitialized value $insertVar in concatenation (.) or string 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
my
文件中声明的变量(在卷曲之外)在文件完成执行时超出范围(在 require
和 use
return 之前)。
$insertVar
只有在文件被sub捕获后才会继续存在,并且只有捕获它的sub可见。
出于效率原因,潜艇捕获尽可能少的变量。如果 sub 没有引用 $insertVar
,它就不会捕获它。由于您的第一个 testSub
没有引用 $insertVar
,因此它不会捕获它。由于在您调用 testSub
时 $insertVar
已经超出范围,因此它对 eval
不可用。您应该收到警告 Variable "$insertVar" is not available
,但出于我不知道的原因,它是针对您使用的特定代码发出的。
您的第二个 testSub
引用 $insertVar
,因此 testSub
捕获 $insertVar
并使其保持活动状态。尽管在您调用 testSub
时 $insertVar
已经超出范围,但由于它被子程序捕获,因此 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