Perl 作用域
Perl eval scope
根据 perldoc,String Eval 应该在当前范围内执行。但是下面的简单测试似乎与此矛盾。
我们需要以下两个简单的文件来设置测试。请将它们放在同一个文件夹下。
test_eval_scope.pm
package test_eval_scope;
use strict;
use warnings;
my %h = (a=>'b');
sub f1 {
eval 'print %h, "\n"';
# print %h, "\n"; # this would work
# my $dummy = \%h; # adding this would also work
}
1
test_eval_scope.pl
#!/usr/bin/perl
use File::Basename;
use lib dirname (__FILE__);
use test_eval_scope;
test_eval_scope::f1();
当我运行程序的时候,出现如下错误
$ test_eval_scope.pl
Variable "%h" is not available at (eval 1) line 1.
我的问题是为什么变量 %h 超出范围。
我做了一些修改,发现如下:
- 如果我 运行 没有 eval(),就像上面的评论一样,它将起作用。
这意味着 %h 应该在范围内。
- 如果我只是在代码中添加一个看似无用的提及,如上
评论,eval() 也可以。
- 如果我将 pl 和 pm 文件合并到一个文件中,eval() 也可以工作。
- 如果我用 'our' 而不是 'my' 声明 %h,eval() 也会起作用。
我在编写一个在运行 时间内解析用户提供的代码的大程序时遇到了这个问题。我不需要解决方案,因为上面有很多解决方法。但我无法解释为什么上面的代码不起作用。这影响了我对 perl 的自豪感。
我的 perl 版本是 linux 上的 v5.26.1。
感谢您的帮助!
潜艇只捕获他们使用的变量。由于 f1
不使用 %h
,它不会捕获它,并且 %h
在模块完成执行后超出范围后变得无法访问 f1
。
对 var 的任何引用(包括优化掉的引用)都会导致 sub 捕获变量。因此,以下内容确实有效:
sub f1 {
%h if 0;
eval 'print %h, "\n"';
}
演示:
$ perl -M5.010 -we'
{
my $x = "x";
sub f { eval q{$x} }
sub g { $x if 0; eval q{$x} }
}
say "f: ", f();
say "g: ", g();
'
Variable "$x" is not available at (eval 1) line 1.
Use of uninitialized value in say at -e line 8.
f:
g: x
根据 perldoc,String Eval 应该在当前范围内执行。但是下面的简单测试似乎与此矛盾。
我们需要以下两个简单的文件来设置测试。请将它们放在同一个文件夹下。
test_eval_scope.pm
package test_eval_scope;
use strict;
use warnings;
my %h = (a=>'b');
sub f1 {
eval 'print %h, "\n"';
# print %h, "\n"; # this would work
# my $dummy = \%h; # adding this would also work
}
1
test_eval_scope.pl
#!/usr/bin/perl
use File::Basename;
use lib dirname (__FILE__);
use test_eval_scope;
test_eval_scope::f1();
当我运行程序的时候,出现如下错误
$ test_eval_scope.pl
Variable "%h" is not available at (eval 1) line 1.
我的问题是为什么变量 %h 超出范围。
我做了一些修改,发现如下:
- 如果我 运行 没有 eval(),就像上面的评论一样,它将起作用。 这意味着 %h 应该在范围内。
- 如果我只是在代码中添加一个看似无用的提及,如上 评论,eval() 也可以。
- 如果我将 pl 和 pm 文件合并到一个文件中,eval() 也可以工作。
- 如果我用 'our' 而不是 'my' 声明 %h,eval() 也会起作用。
我在编写一个在运行 时间内解析用户提供的代码的大程序时遇到了这个问题。我不需要解决方案,因为上面有很多解决方法。但我无法解释为什么上面的代码不起作用。这影响了我对 perl 的自豪感。
我的 perl 版本是 linux 上的 v5.26.1。
感谢您的帮助!
潜艇只捕获他们使用的变量。由于 f1
不使用 %h
,它不会捕获它,并且 %h
在模块完成执行后超出范围后变得无法访问 f1
。
对 var 的任何引用(包括优化掉的引用)都会导致 sub 捕获变量。因此,以下内容确实有效:
sub f1 {
%h if 0;
eval 'print %h, "\n"';
}
演示:
$ perl -M5.010 -we'
{
my $x = "x";
sub f { eval q{$x} }
sub g { $x if 0; eval q{$x} }
}
say "f: ", f();
say "g: ", g();
'
Variable "$x" is not available at (eval 1) line 1.
Use of uninitialized value in say at -e line 8.
f:
g: x