为什么在 Raku 函数签名中使用双分号?

Alv*_*Pan 10 raku

Raku函数文档中,有一个示例如下:

\n
enum DebugType <LOG WARNING ERROR>;\n \n#|[ Prints a message to stderr with a color-coded key. ] \nproto debug(DebugType:D $type, Str:D $message --> Bool:_) {\n    note sprintf qb/\\e[1;%dm[%s]\\e[0m %s/, {*}, $type.key, $message\n}\nmulti debug(LOG;; Str:D --> 32)     { }\nmulti debug(WARNING;; Str:D --> 33) { }\nmulti debug(ERROR;; Str:D --> 31)   { }\n
Run Code Online (Sandbox Code Playgroud)\n

我正在尝试弄清楚LOGWARNING、 和后双分号的用法ERROR,并且只能在Raku Signatures 文档中找到它。在副标题“长名字”下,写着:

\n

“要在多重调度中排除某些参数,请用双分号分隔它们。”\n其示例代码为:

\n
multi sub f(Int $i, Str $s;; :$b) { say "$i, $s, {$b.raku}" };\nf(10, \'answer\');\n# OUTPUT: \xc2\xab10, answer, Any\xe2\x90\xa4\xc2\xbb\n
Run Code Online (Sandbox Code Playgroud)\n

但是在上面的多重调试子程序中,为什么我们必须在多重分派中排除它们的第一个参数?一旦排除它们,Raku 如何知道要调度哪个调试子程序?我尝试用“正常”单逗号替换每个双分号,但在输出中找不到任何不同之处。此外,f子示例让我感到困惑。那里只有一台多低音炮。双分号如何影响其调度?副标题“长名字”也很奇怪。预先非常感谢您的任何解释。

\n

Jon*_*ton 15

参数分隔符的作用;;是表明其后面的参数不参与多重分派过程。因此,在调试示例中,在决定分派到什么内容时仅考虑日志级别值。

术语“长名称”表达了这样的想法:候选multi者的身份不仅仅是子例程的名称,例如“debug”,还涉及其参数的类型(或直到;;)。这是看待它的一种方式 - 事实上,在像 C++ 这样的语言中,长名称确实是作为编译过程的一部分生成的 - 尽管在 Raku 的情况下,候选者multi被保存在附加到控制的列表中proto,而不是名称 -损坏并放入符号表中。

在实践中使用;;相对较少。我想说它的最佳用途是与程序的读者沟通哪些参数用于选择调度候选者,哪些不是。

没有真正的性能原因需要使用;;,或者至少在 MoarVM 上没有。虽然看起来可能会减少运行时的工作量,但实际上 JIT 通过输入类型来专门化热路径子/方法,并且在检查;;专门化是否可以使用之后会考虑参数。

  • 乔纳森,非常感谢您的详细说明。我很抱歉我的英语理解能力很差。但我认为文档作者应该更明确地指出,双分号后面的所有参数都不参与多重分派过程,就像你说的那样。 (2认同)
  • alvaplan,我打算建议您可能想在 raku docs github issues 上提出这个问题,然后我注意到这个问题已经被一个乐于助人的精灵打开了:https://github.com/Raku/doc/issues /4268 ...请随时在该线程上提出更好的措辞并反馈您的回复... (2认同)