如何获取 multi sub 或 build-ins 的所有签名?

How to get all the signatures of multi sub or build-ins?

我定义了一个 multi sub 有两个签名:

multi sub mie(Str $s, Int $i) { $s x $i }
multi sub mie(Int $s, Int $i) { ... }
say &mie.signature; # ;; Mu | is raw)

我想得到这个multi sub的签名,但是上面的结果不是我想要的

如文档所述,contains 是一种具有 4 个签名的多重方法:

multi method contains(Str:D: Cool:D $needle)
multi method contains(Str:D: Str:D $needle)
multi method contains(Str:D: Cool:D $needle, Int(Cool:D) $pos)
multi method contains(Str:D: Str:D $needle, Int:D $pos)

但是当我试图获得 contains 的签名时:

say "a string".^methods.pairs.values[8].value.signature; 

只输出一个签名:

(Str: | is raw)

在 REPL 中,当我调用不带参数的 contains 方法时,它输出以下错误:

> "a string".contains()
Cannot resolve caller contains(Str: ); none of these signatures match:
    (Str:D: Cool:D $needle, *%_)
    (Str:D: Str:D $needle, *%_)
    (Str:D: Cool:D $needle, Cool:D $pos, *%_)
    (Str:D: Str:D $needle, Int:D $pos, *%_)
  in block <unit> at <unknown file> line 1

说明contains方法确实有4个签名!我想知道有什么方法可以输出一个method/multi方法的所有signature吗?

尝试"a string".^lookup('contains').candidates».signature

.^lookup('contains') 会找到 Method

.candidates 将列出多个 candidates

.signature 会给你每个 Signature

输出: ((Str:D: Cool:D $needle, *%_) (Str:D: Str:D $needle, *%_) (Str:D: Cool:D $needle, Cool:D $pos, *%_) (Str:D: Str:D $needle, Int:D $pos, *%_))

您也可以将其用于 multi sub

say &mie.candidates».signature;

作为对 Curt 回答的补充:

proto foo (;; Mu | is raw) {*}               # proto(;; Mu | is raw)

multi foo ($a)             { }               # multi($a)
multi foo (Int $a)         { }               # multi(Int $a)

multi foo ($a,$b)          { }               # multi($a, $b)
multi foo (Int $a,$b)      { }               # multi(Int $a, $b)

say 'proto', .signature for &foo;            # displays 1 line
say 'multi', .signature for &foo.candidates; # displays 4 lines

我已经展示了 say 的结果以及它们各自的例程。

如果你调用 foo ...,其中 foo 是一个多重分派例程(与 .foo 相同),那么,至少在语义上,你实际上是在调用 proto为该名称声明,然后(通常)重新分配到具有相同名称的最合适的 multi

(如果您在 &foo 上调用方法,而不是在 foo 上调用方法,那么您是在 protoRoutine 对象上调用它们。)

手动声明 proto 提供对调度过程的完全控制。它可以泡一杯茶,然后使用 Common Lisp 调度语义,然后 fiddle 结果。或者它想做的任何其他事情。

如果声明了一个或多个 multi 而没有明确声明 proto,则会自动生成默认的 proto。我已手动声明 proto 以支持以下内容:

  • 签名中的 ;;proto sig 中的参数排除在与“赢得”初始发送相关的信息之外——无论如何,proto “赢得”初始调度并获得所有参数;

  • Mu 参数类型约束明确地为 | parameter, which parameter binds to the entire list of arguments passed to it (in a Capture), and the is raw 提供了最广泛的可能类型,这意味着捕获以其“原始”形式接收(我目前不明白这个特性在这里做什么;我原以为 Capture 根据定义是原始的、未处理的参数列表)。

  • 主体然后分派到下一个相同命名的例程(这就是 {*} 所做的)。

我不久前为此制作了 P6Repl::Helper 模块。