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

DVK*_*DVK 4 perl

这有效:

use strict;
X("xxxxxx");
sub X { print shift;}
Run Code Online (Sandbox Code Playgroud)

这会产生错误:

use strict;
BEGIN {
    X("xxxxxx");
}
sub X { print shift;}
Run Code Online (Sandbox Code Playgroud)

错误:

Undefined subroutine &main::X called at ./test.pl line 5.
Run Code Online (Sandbox Code Playgroud)

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

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

use strict;
sub X;
BEGIN {
    X("xxxxxx");
}
sub X { print shift;}
Run Code Online (Sandbox Code Playgroud)

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

perldoc perlsub 似乎没有任何消息.

amo*_*mon 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
Run Code Online (Sandbox Code Playgroud)

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

INIT {
    foo("xxx");
}

sub foo { print shift }
Run Code Online (Sandbox Code Playgroud)

BEGIN 和朋友们都记录在案 perldoc perlmod


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