6

这是一个简短的 Perl 6 程序,它声明了一个MAIN子例程。如果我直接执行程序,我应该只看到输出:

$ cat main.pm6
sub MAIN { say "Called as a program!" }

当我直接执行程序时,我看到了输出:

$ perl6 main.pm6
Called as a program!

如果我将它作为一个模块加载,我看不到任何输出:

$ perl6 -I. -Mmain -e "say 'Hey'"
Hey

如果我use从程序内部进行相同的操作,我看不到任何输出:

$ perl6 -I. -e 'use main'

但是,如果我使用require,我会得到输出:

$ perl6 -I. -e 'require <main.pm6>'
Called as a program!

Synopsis 06字面意思是直接调用编译单元而不是被要求require因为在运行时有效(尽管 S06 不排除它),是否还有其他事情发生?

Rakudo Star 2016.07 和 2016.10 的行为相同。

4

2 回答 2

4

首先,让我们看一下require应该如何表现:

根据(非权威)设计文件

或者,可以直接提到一个文件名,它安装一个对当前词法范围有效匿名的包,并且只能通过模块安装的任何全局名称访问:

只有明确提及的名称才能如此导入。为了保护lexical pad的运行时神圣性,它不能被修改require

结合S06

当且仅当以下情况下执行此调用:

a) 直接调用编译单元,而不是被另一个编译单元要求 [...]

据我了解,MAIN不应运行未明确导入主线词法范围的子程序。

可悲的是,用户文档在通过文件名导入运行时的情况下很安静,并且快速浏览(权威)测试套件(特别是S11-modules/require.t)也没有产生答案,尽管我可能会错过了。

现在,让我们看看 Rakudo 的行为方式:

正如预期的那样,通过静态或动态模块名称进行运行时导入

require main;

或者

require ::('main');

MAIN除非它被声明并显式导入,否则不会运行is export,即

require main <&MAIN>;

require ::('main') <&MAIN>;

分别。

但是通过文件名导入

require 'main.pm6';

将立即运行MAIN

事实上,如果你通过

require 'main.pm6' <&MAIN>;

sub 将被执行两次:一次是在加载编译单元时,第二次是在运行时查找并运行MAIN主线范围内的任何 sub 时。

Rakudo 显然require或多或少地将带有文件名的参数视为并执行它的主线,包括它遇到的EVALFILE任何子线。MAIN

不是我所期望的,可能只是一个错误。

于 2016-11-25T12:23:52.510 回答
0

概要文件不是事实的来源,并且在大多数地方通常已经过时。

您使用/要求的方式也可以改变模块加载方式的行为。-M 不采用“使用 xxx”代码路径,并且使用文件名而不是模块名也会改变事情。请注意,zef 'use'-es 是一个带有 MAIN 的模块并显示输出https://github.com/ugexe/zef/blob/master/bin/zef

于 2016-11-24T14:53:12.500 回答