如果文件是必需的,Perl 6应该运行MAIN吗?

bri*_*foy 6 perl6 modulino

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

$ cat main.pm6
sub MAIN { say "Called as a program!" }
Run Code Online (Sandbox Code Playgroud)

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

$ perl6 main.pm6
Called as a program!
Run Code Online (Sandbox Code Playgroud)

如果我将其作为模块加载,我看不到输出:

$ perl6 -I. -Mmain -e "say 'Hey'"
Hey
Run Code Online (Sandbox Code Playgroud)

如果我use在程序内部相同,我看不到输出:

$ perl6 -I. -e 'use main'
Run Code Online (Sandbox Code Playgroud)

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

$ perl6 -I. -e 'require <main.pm6>'
Called as a program!
Run Code Online (Sandbox Code Playgroud)

概要06字面上说,编译单元是直接调用而不是被要求.是否有其他事情发生,因为require在运行时工作(虽然S06不排除它)?

我对Rakudo Star 2016.07和2016.10也有同样的行为.

Chr*_*oph 4

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

根据(非权威)设计文件

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

只有明确提到的名称才可以这样导入。为了保护词汇垫的运行时神圣性,它不能被 修改require

与S06结合使用

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

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

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

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

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

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

require main;
Run Code Online (Sandbox Code Playgroud)

或者

require ::('main');
Run Code Online (Sandbox Code Playgroud)

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

require main <&MAIN>;
Run Code Online (Sandbox Code Playgroud)

require ::('main') <&MAIN>;
Run Code Online (Sandbox Code Playgroud)

分别。

但是通过文件名导入

require 'main.rakumod';
Run Code Online (Sandbox Code Playgroud)

就会立刻跑MAIN

事实上,如果你通过正确的导入

require 'main.rakumod' <&MAIN>;
Run Code Online (Sandbox Code Playgroud)

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

requireRakudo 显然或多或少地对待带有文件名参数EVALFILE并执行其主线,包括它遇到的任何子线MAIN

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