这是一个简短的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也有同样的行为.
首先,让我们看看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。
这不是我所期望的,可能只是一个错误。
| 归档时间: |
|
| 查看次数: |
154 次 |
| 最近记录: |