perl eval使用在包中声明的未初始化值

时间:2015-06-16 15:00:03

标签: perl scope package eval lexical

任何人都可以向我解释为什么eval函数无法访问包中声明的变量,除非在sub中使用了一次?
(perl v5.16.3 MSWin32-x64-multi-thread 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" ;

执行程序时的结果:

  

在连接(。)或字符串中使用未初始化的值$ insertVar   在(eval 1)第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

1 个答案:

答案 0 :(得分:1)

文件(curlies之外)中声明的

my变量在文件完成执行后(在requireuse返回之前)超出范围。

$insertVar只有在文件完成执行后才会继续存在,如果它被子捕获,它只会被捕获它的子视图看到。

出于效率原因,subs捕获尽可能少的变量。如果子没有引用$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 声明变量,它们将成为全局包变量,因此不会超出范围,并且{{1}可以使用它们}。

String[] dataFileds = new String[]{
            MediaStore.MediaColumns.DATA,
            OpenableColumns.DISPLAY_NAME,
            OpenableColumns.SIZE};

    Cursor cursor = context.getContentResolver().query(uri, dataFileds, null, null, null);
    cursor.moveToFirst();

    fileLocation = cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.DATA));
    title = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
    size = cursor.getInt(cursor.getColumnIndex(OpenableColumns.SIZE));

    cursor.close();