查找本地编译的 Raku 模块

Finding locally compiled Raku modules

如何找到本地安装的模块,以及我可以在 Raku 程序中 use 的模块?

假设我们有三个分布:Parent, Brother, Sister。 Parent'provides'Top.rakumod,兄妹分别提供'Top::Son.rakumod'和'Top::Daughter.rakumod'。兄妹有一个 'depends': 'Top' 在他们的 META6.json.

每个发行版都在其自己的 git 存储库中。而且每一个都是由zef安装的。

假设 Top 设置为带有接口方法的 class,可能类似于:multi method on-starting { ... },每个 sub-class 必须实现,而当 运行,向调用者提供有关 sub-class 的信息。所以 Top::BrotherTop::Daughter 都实现了 on-starting。也可能有未在本地安装的发行版 Top::Aunt 等。我们需要找到安装了哪些。

所以,现在我们 运行 一个 Top 的实例(定义在 Parent 中)。它需要寻找匹配 Top::* 的已安装模块。开始的地方(我认为)是 $*REPO,它是包含已安装模块的存储库的链接列表。 $*REPO 也执行 CompUnit::Repository 角色,后者又具有 'need' 方法。

我不明白的是如何操纵 $*REPO 来获取与 Top::* 匹配的所有候选模块的列表,以及整个链表。

获得候选列表后,我可以使用 ^can 来检查它是否具有 on-starting 方法,然后调用该方法。

如果这不是获得 Top 发现本地安装模块的结果的方法,我将不胜感激我刚才提出的方案的一些替代方案。

CompUnit::Repository (CUR) 有一个 candidates 搜索分布的方法,但它不允许按名称前缀搜索(因为它也进行快速查找,需要全名才能获得其sha1 directory/lookup)。对于 CompUnit::Repository::FileSystem (CURFS) 你可以调用 .distribution 来获取它提供的分布,对于 CompUnit::Repository::Installation (CURI) 你可以调用 .installed 来获取它提供的所有分布:

raku -e '                                                                                        \
    say $*REPO.repo-chain                                                                        \
        .grep(CompUnit::Repository::FileSystem | CompUnit::Repository::Installation)             \ 
        .map({ $_ ~~ CompUnit::Repository::FileSystem ?? $_.distribution !! $_.installed.Slip }) \
        .grep(*.defined)                                                                         \
;'

如果你想匹配命名空间,你需要在发行版名称或其模块名称上进行 grep:

my @matches = @distributions.grep({ $_.meta<provides>.keys.first({.starts-with("Top::")}) });

这种处理方式可以在 Pluggable 模块中看到(如果你也想加载这样的代码,我建议使用它)

当然,您明确要求仅安装模块,但忽略 CURFS 没有任何意义——作为应用程序开发人员,加载模块的位置或方式不重要。如果有人想使用 -I ./foo 而不是安装它,那么没有理由忽略它。如果您无论如何都坚持这样做,那么如何更改上面的示例以适应应该是显而易见的。

Once I have the list of candidates, I can use ^can to check it has a on-starting method, and then call that method.

除了检查元文件或窃取各种文件的源代码外,拥有候选名单不会让您做任何事情。至少你会加载任何你想调用的模块,例如.^can 首先,其中将涉及几个步骤,分布对象不能直接用于加载(您从中提取全名并使用它来加载它)--所以我再次建议使用 Pluggable