你能告诉你的代码何时在eval块中吗?

时间:2014-11-24 15:49:28

标签: perl eval subroutine

我的代码(Perl库中的方法)是否有办法判断它是否是从eval {}块中执行的?

我想拥有的是:

sub mySub {
    my $isInEval = isInEval();
    if ($isInEval) {
        # Do a dying thing
    } else {
        # Do a non-dying thing.
    }
}

对于与推出复杂性相关的问题,我无法将死亡和非死亡代码折叠到同一个相同的代码块中,如果我们在eval内部,则无关紧。

1 个答案:

答案 0 :(得分:1)

好的,明白了。 perldoc caller说:

# 0 1 2 3 4
($package, $filename, $line, $subroutine, $hasargs,
# 5 6 7 8 9 10
$wantarray, $evaltext, $is_require, $hints, $bitmask, $hinthash)
= caller($i);
  

请注意,如果帧不是子例程调用,则子例程可能是(eval),而是eval。在这种情况下,设置了额外的元素$ evaltext和$ is_require:如果框架是由require或use语句创建的,则$ is_require为true,$ evaltext包含eval EXPR语句的文本。特别是,对于eval BLOCK语句,$子例程是(eval),但$ evaltext是未定义的。

我使用

测试了这个
  

perl -e'使用Data :: Dumper; sub x {foreach my $ i(0..5){my @ c = caller($ i); print Data :: Dumper-> Dump( [\@C])} }; sub y1 {x()}; sub z {eval {y1()}}; sub z2 {z();}; Z2()'

事实上,#4呼叫caller[3]输出为

$VAR1 = [
      'main',
      '-e',
      1,
      '(eval)',
      0,
      undef,
      undef,
      undef,
      0,
      ''
    ];

最终代码:

 sub isInEval{ 
     my $i=0; 
     while(1) {
        my ($package, $filename, $line, $subroutine, $hasargs
           ,$wantarray, $evaltext, $is_require, $hints, $bitmask, $hinthash)
            = caller($i); 
        last unless defined $package; 
        $i++; 
        if ($subroutine eq "(eval)" || $evaltext) { 
            return 1;
        } 
    }; 
    return 0; 
}
sub x {
    if (isInEval()) {
        print "eval\n";
    } else {
        print "NO eval\n";
    }
}
sub y1 { x() }; 
sub z1 { eval{y1()} }; 
sub w1 { z1(); }; 
print "w1: eval expected: ";
w1();

sub y2 { x() }; 
sub z2 { y2() }; 
sub w2 { z2(); }; 
print "w2: eval UNexpected: ";
w2();