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

huangapple go评论58阅读模式
英文:

why use double semicolon in Raku function signature?

问题

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

enum DebugType <LOG WARNING ERROR>;

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

我试图弄清楚在LOGWARNINGERROR后面为什么有双分号的用法,只能在Raku签名文档中找到相关信息。在标题"长名称"下,它说:

"为了排除某些参数不被考虑在多重分发中,用双分号分隔它们。"
并提供了以下示例代码:

multi sub f(Int $i, Str $s;; :$b) { say "$i, $s, {$b.raku}" };
f(10, 'answer');
# 输出: "10, answer, Any"

但在上面的多重debug子例子中,为什么我们要排除它们的第一个参数不被考虑在多重分发中呢?一旦它们被排除,Raku如何知道要分派到哪个debug子例子?我尝试用一个普通的逗号替换每个双分号,但在输出中找不到任何不同之处。此外,f子例子让我感到困惑。那里只有一个多重子例子。双分号如何影响它的分派?"长名称"的子标题也很奇怪。非常感谢任何详细的解释。

英文:

In Raku functions documentation, there is an example as follows:

enum DebugType &lt;LOG WARNING ERROR&gt;;
 
#|[ Prints a message to stderr with a color-coded key. ] 
proto debug(DebugType:D $type, Str:D $message --&gt; Bool:_) {
    note sprintf qb/\e[1;%dm[%s]\e[0m %s/, {*}, $type.key, $message
}
multi debug(LOG;; Str:D --&gt; 32)     { }
multi debug(WARNING;; Str:D --&gt; 33) { }
multi debug(ERROR;; Str:D --&gt; 31)   { }

I am trying to figurue out the usage of double semicolons after LOG, WARNING, and ERROR, and can only find it in Raku Signatures documentation. Under subtitle 'Long names', it's said that:

"To exclude certain parameters from being considered in multiple dispatch, separate them with a double semicolon."
And its example code is:

multi sub f(Int $i, Str $s;; :$b) { say &quot;$i, $s, {$b.raku}&quot; };
f(10, &#39;answer&#39;);
# OUTPUT: &#171;10, answer, Any␤&#187;

But in the above multi debug subs, why do we have to exclude their first argument from being considered in multiple dispatch? Once they are excluded, how could Raku know which debug sub to dispatch? I tried to replace each double semicolon with a 'normal' single comma, but could not find anything different in the output. Besides, the f sub example makes me puzzled. There's only one multi sub there. How double semicolon affect its dispatch? The subtitle 'Long names' is weird, too. Thanks a lot in advance for any kind explanation.

答案1

得分: 15

The purpose of the ;; parameter separator is to indicate that the parameters after it do not participate in the multiple dispatch process. Thus in the debug example, only the log level value is considered when deciding what to dispatch to.

The term "long name" is expressing the idea that the identity of the multi candidate is not just the name of the subroutine, such as 'debug', but also involves the types of its parameters (or those up to the ;;). It's one way to look at it - in fact, in a language like C++ a long name really is generated as part of the compilation process - although in Raku's case the multi candidates are held in a list attached to the controlling proto, rather than being name-mangled and put into a symbol table.

Use of ;; is relatively rare in practice. I'd say its best use is in communicating to the reader of the program which parameters are used to select the dispatch candidate and which aren't.

There's not really a performance reason to use ;;, or at least not on MoarVM. While it might look like it would cause less work at runtime, in reality the JIT specializes hot-path subs/methods by their input types, and that would consider arguments after the ;; in checking that the specialization can be used.

英文:

The purpose of the ;; parameter separator is to indicate that the parameters after it do not participate in the multiple dispatch process. Thus in the debug example, only the log level value is considered when deciding what to dispatch to.

The term "long name" is expressing the idea that the identity of the multi candidate is not just the name of the subroutine, such as 'debug', but also involves the types of its parameters (or those up to the ;;). It's one way to look at it - in fact, in a language like C++ a long name really is generated as part of the compilation process - although in Raku's case the multi candidates are held in a list attached to the controlling proto, rather than being name-mangled and put into a symbol table.

Use of ;; is relatively rare in practice. I'd say its best use is in communicating to the reader of the program which parameters are used to select the dispatch candidate and which aren't.

There's not really a performance reason to use ;;, or at least not on MoarVM. While it might look like it would cause less work at runtime, in reality the JIT specializes hot-path subs/methods by their input types, and that would consider arguments after the ;; in checking that the specialization can be used.

huangapple
  • 本文由 发表于 2023年3月12日 10:25:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/75710748.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定