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

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

问题描述:

这有效:

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 时正处于编译阶段......所以编译器还没有进入 sub 声明/定义.

This makes sense, since we are in the middle of compile phase when executing the sub... so the compiler didn't get to the sub declaration/definition yet.

...但是:添加前向声明(在 BEGIN 块之前或内部)没有帮助:

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

为什么在 BEGIN 块中调用函数时前向声明不起作用?我假设它发生在编译阶段,就像 my 声明一样.

Why doesn't the forward declaration work when the function is called in the BEGIN block? I would assume that it takes place during compile phase, the way my declaration does.

perldoc perlsub 似乎没有任何意义.

BEGIN 块被解析后立即执行.这意味着 perl 还没有看到 sub 的定义1.您唯一的解决方案是在使用之前定义函数:

A BEGIN block is executed as soon as it has been parsed. This means that perl has'nt seen the definition of the sub yet1. Your only solution is to define the function before it's used:

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:

You could also choose a phaser that's executed later, e.g. INIT:

INIT {
    foo("xxx");
}

sub foo { print shift }

BEGIN 和朋友记录在 perldoc perlmod

BEGIN and friends are documented in perldoc perlmod

  1. sub foo; 这样的预声明仅在原型上下文中为解析器提供指导,以及裸字与子例程调用消歧.它不会使解析器跳转到实际定义.由预声明生成的子例程存根实际上是不可调用的.
  1. A pre-declaration like sub foo; only provides guidance for the parser in the context of prototypes, and the bareword vs. subroutine call disambiguation. It does not make the parser jump forward to the actual definition. The subroutine stub generated by a predeclaration is not actually callable.