【问题标题】:How to get all the signatures of multi sub or build-ins?如何获得多子或内置的所有签名?
【发布时间】:2023-03-28 22:22:01
【问题描述】:

我定义了一个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 个签名!我想知道有没有方法可以输出一个方法/多方法的所有signature

【问题讨论】:

    标签: raku


    【解决方案1】:

    试试"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 &amp;mie.candidates».signature;

    【讨论】:

    • 非常感谢!
    【解决方案2】:

    作为对 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
    

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

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

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

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

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

    • 签名中的;; 排除了proto sig 中的参数与“赢得”对它的初始调度相关——无论如何,proto“赢得”初始调度并获得所有论据;

    • Mu 参数类型约束明确地为| parameter 提供最广泛的类型,该参数绑定到传递给它的整个参数列表(在Capture 中),is raw 表示捕获以它的“原始”形式接收(我目前不明白这个特征在这里做了什么;我原以为Capture 定义为一个原始的、未处理的参数列表)。

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

    【讨论】:

      【解决方案3】:

      我不久前为此创建了P6Repl::Helper 模块。

      【讨论】:

      • 我刚刚安装了模块,它运行良好,感谢您的出色工作。
      猜你喜欢
      • 1970-01-01
      • 2017-12-14
      • 2019-09-29
      • 2021-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多