7

当 proto 和 multis 在同一个模块中定义时,Type.^lookup('method').candidates返回所有 multi 候选者的列表。但是,当 proto 位于与 multis 不同的文件/模块中时,这似乎不起作用。

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

有没有什么办法可以通过Raku的自省找到完整的多位候选人名单?或者除了通过源代码搜索之外别无选择?(我问是因为拥有适用于给定原型的多个候选人的完整列表将有助于文档目的。)

4

1 回答 1

6

就目前而言multi methods,这与在同一个模块或文件中根本没有关系。考虑这些类:

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

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

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

然而,我刚刚描述的过程有点简化了实际发生的事情。步骤是:

  1. 看看这个类是否proto已经有了;如果是这样,添加multi到它
  2. 否则,查看是否有任何基类具有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以及新条目。

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

于 2020-08-20T12:07:27.413 回答