【问题标题】:Detect compile phase in Perl在 Perl 中检测编译阶段
【发布时间】:2014-11-02 02:40:57
【问题描述】:

我正在使用一个模块,该模块利用一些原型来允许代码块。例如:

sub SomeSub (&) { ... }

由于原型仅在编译时解析时才有效,如果在编译时未解析模块,我想抛出警告甚至致命。例如:

require MyModule; # Prototypes in MyModule won't be parsed correctly

有没有办法检测在 Perl 的编译或运行时/阶段是否正在执行某些东西?

【问题讨论】:

  • 这是个坏主意。在运行时加载模块有完全正当的理由——即使是大量使用原型的模块。
  • 这可能是一个好主意或坏主意,具体取决于每种情况的原因。如果特定模块的全部目的是创建仅在编译时加载时才有效的功能,那么至少有一个很好的理由警告用户该模块在运行时被无用地加载。
  • 不,这仍然是个坏主意。 Perl 不仅有一个编译时/运行时。 use strict 具有完全编译时的效果,但我的模块执行sub import { require strict; require Import::Into; strict->import::into(caller) } 之类的操作是完全明智的。我的模块在运行时加载strict,但在调用者的编译期间它被导入到调用者的模块中。没错,我的模块的运行时间发生在调用者的编译时间。
  • 在运行时加载模块的另一个好理由...我可能不想实际使用您的模块,而只是报告它的版本。 require Your::Module; printf "Your::Module %s installed\n", Your::Module->VERSION;。例如,这可以在设置或诊断脚本中完成,以报告所有应用程序先决条件的已安装版本。
  • 如果您在编译时在脚本中调用use module,“模块”中的所有内容都会在编译时解析,包括您刚刚用作示例的内容。无论如何,这与我提出的场景无关,即确保在全局编译时正确解析原型,因为在那之后,根本就没有办法了。

标签: perl runtime compile-time


【解决方案1】:

如果您在 Perl 5.14 或更高版本上运行,则可以使用包含当前编译器状态的特殊 ${^GLOBAL_PHASE} 变量。这是一个例子。

use strict;
use warnings;

sub foo {
    if ( ${^GLOBAL_PHASE} eq 'START' ) {
        print "all's good\n";
    } else {
        print "not in compile-time!\n";
    }
}

BEGIN {
    foo();
};

foo();

输出:

all's good
not in compile-time!

【讨论】:

  • 很好,感谢您的回答。你知道早期版本的方法吗?
  • @FranciscoZarabozo 你可以试试INIT {} 块。它应该只在模块在 BEGIN 中加载时才起作用(例如使用use)。
【解决方案2】:

在 5.14 之前(或之后或之后),您可以这样做:

package Foo;
BEGIN {
    use warnings 'FATAL' => 'all';
    eval 'INIT{} 1' or die "Module must be loaded during global compilation\n";
}

但是(和${^GLOBAL_PHASE})并不能完全检查您想知道的内容,即包含 use/require 语句的代码是否正在编译或运行。

【讨论】:

  • 我试过这个答案,但没有奏效。当使用require 而不是use:Too late to run INIT block at (eval 11) line 1. 时,我得到的只是一个警告(当然,启用了警告),但它并没有真正失败,它永远不会到达死调用(退出代码为 0) .
  • 在阅读了您的版本问题后,我在 Perl 5.20 和 5.12 上进行了尝试。 eval 没有失败。
  • 哦,原来如此。 :-)
猜你喜欢
  • 1970-01-01
  • 2014-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-05
  • 1970-01-01
  • 2016-04-23
相关资源
最近更新 更多