为什么即使使用前向声明,我也不能在BEGIN块中调用后来定义的子?

时间:2014-03-27 16:23:27

标签: perl

这有效:

use strict;
X("xxxxxx");
sub X { print shift;}

这会产生错误:

use strict;
BEGIN {
    X("xxxxxx");
}
sub X { print shift;}

错误:

Undefined subroutine &main::X called at ./test.pl line 5.

这是有道理的,因为我们在执行sub ...时处于编译阶段的中间,所以编译器还没有进入子声明/定义。

...但是:添加转发声明(在BEGIN阻止之前或其中)并没有帮助

use strict;
sub X;
BEGIN {
    X("xxxxxx");
}
sub X { print shift;}

为什么在BEGIN块中调用函数时前向声明不起作用?我认为它发生在编译阶段,my声明的方式。

perldoc perlsub似乎没有任何消息。

1 个答案:

答案 0 :(得分:8)

BEGIN块在解析后立即执行 。这意味着perl已经看到了sub 1 的定义。您唯一的解决方案是在使用之前定义功能:

sub foo { print shift }
# When the parser reaches this point, the "foo" sub has been compiled

BEGIN {
    # Ergo, "foo" can be used here
    foo("xxx");
}
# The BEGIN block is executed once the parser arrives here

您还可以选择稍后执行的移相器,例如INIT

INIT {
    foo("xxx");
}

sub foo { print shift }

BEGIN和朋友记录在perldoc perlmod


  1. sub foo;这样的预先声明仅在原型的上下文中为解析器提供指导,而裸字与子例程调用消歧。它不会使解析器跳转到实际定义。由预先声明生成的子例程存根实际上不可调用。