Raku 的自省能否列出所有跨越 files/Modules 的多个候选人?

Can Raku's introspection list all the multi candidates across different files/Modules?

当在同一个模块中定义了 proto 和 multis 时,Type.^lookup('method').candidates returns 所有 multi 候选项的列表。但是,当 proto 与 multis 处于不同的 file/module 时,这似乎不起作用。

say Setty.^lookup('grab').candidates;   # OUTPUT: ()

有没有办法通过Raku的内省找到完整的多候选名单?或者除了 grepping 源代码之外别无选择? (我问是因为拥有适用于给定原型的多个候选人的完整列表将是 helpful for documentation purposes。)

multi methods 而言,这与位于同一模块或文件中根本无关。考虑这些 classes:

class Base {
    proto method m(|) { * }
    multi method m() { 1 }
}

class Derived is Base {
    multi method m() { 2 }
}

每当我们编写包含多个方法的 class 时,我们需要将它们附加到控制 proto。在 Base 的情况下,这是明确写入的,因此除了将 multi 候选者添加到其候选者列表之外别无他法。然而,如果我们没有在 Base 中明确地写一个 proto,那么就会为我们生成一个空的候选列表,最终结果相同。

不过,我刚才描述的过程只是对实际发生的事情进行了一些简化。步骤是:

  1. 看看这个 class 是否已经有一个 proto;如果是这样,请将 multi 添加到其中
  2. 否则,查看是否有任何碱基 class 具有 proto;如果是这样,克隆它(在 tern 中克隆候选列表)并向其添加 multi
  3. 否则,生成一个新的proto

第 2 步确实是您问题的答案。如果我们这样做:

say "Base:";
.raku.say for Base.^lookup('m').candidates;

say "Derived:";
.raku.say for Derived.^lookup('m').candidates;

则输出为:

Base:
multi method m (Base: *%_) { #`(Method|82762064) ... }
Derived:
multi method m (Base: ) { #`(Method|82762064) ... }
multi method m (Derived: ) { #`(Method|82762208) ... }

也就是说,Base中的候选列表有一个条目,Derived中的候选列表有从Base克隆的条目以及一个新的条目。

几乎所有的东西都遵循这个原则:派生的 classes 引用他们的基础 class(以及他们所做的角色),但是基础 classes(和角色)不知道他们的后代。