使用 rakudo-star 加载 Raku 模块的正确方法是什么?

What is the proper way to load Raku modules using rakudo-star?

我有以下项目

$ tree
.
├── lib
│   └── MyModule.raku
└── main.raku

$ cat lib/MyModule.raku
use v6;
unit module MyModule;
sub hello { say 'hello' }

$ cat lib/main.raku
use v6;
use MyModule;
MyModule.hello();

我想运行main.raku使用最新的rakudo-starimage。但是发生以下情况

$ docker run -i --rm -u $(id -u) \
--workdir /work \
--volume  $PWD:/work \
--entrypoint bash \
rakudo-star perl6 -I ./lib main.raku
===SORRY!===
Could not find MyModule at line 3 in:
    file#/work/lib
    inst#/.perl6
    inst#/usr/share/perl6/site
    inst#/usr/share/perl6/vendor
    inst#/usr/share/perl6
    ap#
    nqp#
    perl5#

我也尝试在 main.raku 中的 use MyModule 之前插入 use lib '/work/lib',结果相同。

新的 Raku 版本使用 .rakumod 作为模块的文件扩展名。仍然支持较旧的 .pm6 扩展。有关新文件扩展名的更多信息,请参见 Path-to-Raku ticket. More information about modules is available in the raku documentation.

有几个问题。

  1. 模块不以 .raku 结尾。它们以 .rakumod.pm6 结尾(暂时)。
    (从技术上讲,安装后,只要在 META6.json 中正确声明扩展名,实际上并不重要。)

  2. 子例程默认是词法作用域 (my),默认也不导出。
    所以没有办法在它定义的模块之外访问 hello()

  3. 模块没有方法,所以不能将hello作为方法来调用。
    即使他们确实有方法,他们也不会以 sub 关键字开头。


您可以使用 our:

在全局范围内定义子例程

lib/MyModule.rakumod

use v6.d;
unit module MyModule;

our sub hello () { say 'hello' }
#^
# \
#  globally scoped

main.raku

use v6.d;
# use lib './lib';
use module MyModule;

MyModule::hello();
#       ^^
#        \
#         namespace delimiter

您可以导出它:

lib/MyModule.rakumod

use v6.d;
unit MyModule;

#             mark for export
#            v-------v
sub hello () is export {
    say 'hello'
}

main.raku

use v6.d;
# use lib './lib';
use MyModule;

hello();

除了is export, there are other more fine grained ways to export

如果您要导出,我建议您也使用 our 将其设为全局。这样,如果有人使用您的模块,但不想导入您的潜艇;他们仍然可以访问它们。