查找本地编译的 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::Brother
和 Top::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
如何找到本地安装的模块,以及我可以在 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::Brother
和 Top::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