这是一个简短的 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 的行为相同。
最佳答案
首先我们来看看require
应该表现得:
根据(非权威)design documents ,
Alternately, a filename may be mentioned directly, which installs a package that is effectively anonymous to the current lexical scope, and may only be accessed by whatever global names the module installs:
和
Only explicitly mentioned names may be so imported. In order to protect the run-time sanctity of the lexical pad, it may not be modified by
require
.
结合 S06的
This call is performed if and only if:
a) the compilation unit was directly invoked rather than by being required by another compilation unit [...]
据我了解,子
MAIN
不应运行未显式导入到主线词法范围中的内容。可悲的是,user documentation在通过文件名导入运行时的情况下很安静,快速浏览一下(权威)test suite (特别是 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
它遇到。这不是我所期望的,可能只是一个错误。
关于raku - 如果需要该文件,Perl 6 是否应该运行 MAIN?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40778852/