6

请看下面的代码:

use strict;
use warnings;


print "subroutine is defined\n" if defined &myf;
myf();

sub myf
{
        print "called myf\n";
}

undef &myf;
#myf();
print "now subroutine is defined\n" if defined &myf;

输出是

subroutine is defined
called myf

第一条print语句可以打印,这是否意味着解释器(或编译器?)进一步查看并看到子例程定义?如果是这样,为什么它不将第二个语句undef &myf;视为第二个print语句?

谢谢

4

1 回答 1

10

这与范围无关,但与compile timerun time有关。这是一个简化的解释。

Perl 解释器将首先扫描您的代码,并遵循任何use语句或BEGIN块。此时,它会看到所有的subs,并将它们记录在各自的包中。所以现在你&::myf的符号表中有一个。

当编译时间到达程序的末尾时,它将切换到运行时间。

那时,它实际上运行代码。如果已定义,则执行您的第一print条语句。&myf我们知道它是,因为它是在编译时设置的。Perl 然后调用该函数。一切都很好。现在你undef在符号表中的那个条目。这也发生在运行时。

之后,defined &myf返回 false,因此不打印。

你甚至在代码中有第二次调用myf(),但被注释掉了。如果您删除评论,它将抱怨Undefined subroutine &main::myf called。这是对发生的事情的一个很好的暗示。

所以实际上它在代码中并没有向前或向后看。那时它已经完成了扫码。


perlmod中解释了不同的阶段。

请注意,实际undef使用函数的用例并不多。我不明白你为什么要删除它,除非你想手动清理你的命名空间。

于 2016-09-20T10:58:32.363 回答