如何阻止代码在编译器阶段运行?

Eva*_*oll 6 perl constants

这个问题需要了解编译器阶段,而不是BEGIN块。来自编程 Perl:第 3 版 - 第 467 页

理解编译阶段和编译时之间以及运行阶段和运行时之间的区别也很重要。典型的 Perl 程序有一个编译阶段,然后是一个运行阶段。“阶段”是一个大尺度的概念。但是编译时间和运行时间是小规模的概念。一个给定的编译阶段主要做编译时的事情,但它也通过BEGIN块做一些运行时的事情。一个给定的运行阶段主要做运行时的事情,但它可以通过像eval STRING.

让我们举一个非常简单的例子

sub complex_sub {
  die 'code run';
}
sleep 5;
print 'good';
use constant FOO => complex_sub();
Run Code Online (Sandbox Code Playgroud)

如果上面按原样运行,那么complex_sub从用户的角度来看,它是在编译器阶段运行的。但是,稍加修改,我就可以..

# Bar.pm
package Bar {
  use constant FOO => main::complex_sub();
}

# test.pl
package main {
  sub complex_sub {
    die 'code run';
  }
  sleep 5;
  print 'good';
  require Bar;
}
Run Code Online (Sandbox Code Playgroud)

上面的代码complex_sub是在执行阶段运行的。有没有办法从complex_sub启用顶层语法,禁止底层语法的角度来区分这两种情况。

cho*_*oba 12

使用${^GLOBAL_PHASE}变量。它在第一种情况下包含“START”,但在第二种情况下包含“RUN”。

# RUN
perl -wE'say ${^GLOBAL_PHASE}'

# START
perl -wE'BEGIN {say ${^GLOBAL_PHASE}}'

# RUN
perl -wE'eval q{BEGIN {say ${^GLOBAL_PHASE}}}'
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅perlvar

  • 值得注意的是 [${^GLOBAL_PHASE}](https://perldoc.pl/variables/$%7B%5EGLOBAL_PHASE%7D) 是在 5.14 中添加的。 (2认同)