【问题标题】:Documentation for the object Signature: " ... different name for a named argument than the variable name"对象签名的文档:“......命名参数的名称与变量名称不同”
【发布时间】:2026-02-04 07:05:01
【问题描述】:

“类签名”页面上的示例显示为:

sub named(:official($private)) { "Official business!" if $private }; named :official;

【问题讨论】:

  • 欢迎来到 SO。如果没有minimal reproducible example,Qs 可能真的很难回答,而您的 Q 就是一个很好的例子。您用英语描述了一个问题——“$private=False 调用'named' 时仍会打印'Official business!'”——但不是代码。我找到了一种获得该结果的方法(在您的 Q 的另一个答案中描述),但它要求我使用椒盐脆饼逻辑。最重要的是,如果我们的答案都没有帮助,请编辑您的 Q 以提供minimal reproducible example。而且,如果您不打算用谜语逗读者,写任何其他 SO,请在首次发布时为他们写一个minimal reproducible example。再次,欢迎来到 SO。 :)
  • 抱歉,如果三重链接感觉怪怪的。我很想删除评论,但现在我只是解释一下自己。 ❶ 写[mre](不是代码)会自动转换成链接。 (写成a [mre] 而不是an [mre]。哎呀。)我第一次去故意避免三重链接,但太长了。切换到[mre] 解决了这个问题。 ❸ 当我发表评论并意识到“啊,我忘记了”时,我认为 MRE 的重点是可以的,也许是有道理的。我希望你没有难过;这当然不是我的意图。

标签: documentation raku


【解决方案1】:

我看到文档示例令人困惑。这是该解释的扩展版本:

sub named(:official($private)) {
   # Inside the function, the argument the caller passed in
   # is bound to the variable $private.  Nothing is bound to official.
   say $private;
}

# Outside the function, the caller doesn't need to care what term the 
# function uses.  All it needs to know is the name of the parameter – :official
named(:official('foo')); # OUTPUT: «foo»

当函数位于不同的模块中时,这特别方便——函数的所有者可以重构他们的 $private 参数的名称,而不会破坏任何外部调用者。而且,如果他们想出一个更好的名称供外部调用者使用,他们甚至可以添加 that 而不会破坏向后兼容性:sub named(:official(:better-name(:$private))) { … } 允许调用者使用 :official:better-name 作为参数名称,对函数内部的变量名没有任何影响。

这样更有意义吗?

哦,还有一个注意事项:

如果 $private=True 则调用 'named' 会打印“Official business!”正如你所料

如果我理解正确,你的意思是写类似的东西

sub named(:official($private)=True) { "Official business!" if $private }

这是你的意思吗?如果是这样,您应该知道该签名中的$private=True 并不是真正设置 $private 任何东西——它只是为变量$private 提供default value。所以你可以得到这个输出:

sub named(:official($private)=True) {
      say $private;
}

named();               # OUTPUT: «True»
named(:official(42));  # OUTPUT: «42»

无论如何,我都会向文档存储库发送一个 PR,并尝试稍微澄清一下命名参数示例。希望你喜欢 Raku!

【讨论】:

  • 我刚刚在 Rakudo 的几个版本中尝试了 sub named(:official($private=True)) { say $private } 并得到了两个版本的编译时错误。你用什么版本来编译它?
  • @raiph,抱歉,这是我的复制粘贴错误(我现在已经修复); ) 需要在 =True 之前,而不是之后。感谢您指出这一点!
  • 嗯。我以为我试过了。 (这是我刚刚发布的答案的一部分。我现在需要修复它......)
  • 谜中之谜。 :) ❶ 我认为它编译。 ❷ 可能会解释 Keith 尝试/看到的内容。 ❸ 但是当我尝试它时,它在编译时失败了。 (之前和之后都有)。)我什至在我的回答中加入了这个“事实”。 ❹我发表了我的答案。 ❺ 我对你的回答写了我的第一条评论。 ❻ 你告诉我它确实 工作! ❼ 啊?!?快速复查。啊!我搞砸了! ❽我编辑了我的答案以删除我的错误“事实”。 ❾(这一切都发生在不到 5 分钟的时间内,所以在我的答案版本中没有记录。)❿ 我不明白它如何解决 Keith 的 Q/谜语......?
  • "它只需要知道参数的名称——:public"。您的意思是 :official 而不是 :public
【解决方案2】:

在这个简短的例子中发生了几件事:

sub named(:official($private)) { "Official business!" if $private }
           -------- --------
               |        |
               |        > '$private' is the name of this var within the sub
               |
               > 'official' is the (sigilless) name of this var outside
           
           ------------------
                   |
                   > ':official($private)' is the 
                            raku Pair 'official => $private'  

named :official
----- ---------
  |       |
  |       > the raku Pair 'official => True' (so $private ~~ True)
  |
  > the same as 'named( official => True );'

所以当你在 repl 中尝试这个时...

> named :official;             #Official business!
> named( official => True )    #Official business! [same thing]
-or-
> named :!official             #()
> named( official => False )   #() [same thing]

第一次遇到,在这个例子中,raku 是相当古怪的。为什么?

  • raku Pair literal 语法可以轻松处理常见的函数参数情况,例如 :dothis:!notthat 副词
  • :name(value) 公式在此处被重新用于将外部变量名称映射到内部变量名称 - 没有什么特别需要,因为 Pair 语法已经做到了 - 但对于代码封装非常有用
  • argument aliases 类似的情况...您可以将其视为 Pairs of Pairs ...再次,不需要特殊语法,因为只需使用内置的 Pair 文字语法

所以,恕我直言,raku 非常酷,因为我们只需要学习一些基本的元素语法(在本例中为 Pair 文字),然后就可以以多种方式一致地应用它们,以简明地解决相当棘手的编码场景。

【讨论】:

    【解决方案3】:

    通过pretzel logic 我得出的结论是:

    • 你的Q可能是为了欺骗我们而精心编写的,如果我们正确解开谜题,你就会揭开真相。

    或者(可能更可能......?):

    • 采用这种心态将帮助我们所有人(您、读者、回答者)玩得开心,因为我们试图解决您真诚 Q 中固有的谜题,即使您打算这样做有趣...

    无论哪种方式,请阅读此答案并让我知道它是否有助于解决谜题。 TIA。 :)


    我错过了什么不是我,而是什么?

    也许这是解开谜题的关键:我们应该问自己“Keith 故意从 Q 中漏掉了什么?”。

    当然,如果是这样,那么您首先要忽略的是它是个谜。在这种情况下,主要的荣誉!如果它不是故意的谜语,好吧,它仍然是一个谜,所以无论如何都值得称赞,让我们尝试解决它!


    @codesection 的答案可能是最有力的线索。虽然您没有编写最小的可重现示例,但您确实编写了 sub 定义代码,并且您确实说您编写了 $private=False

    所以我们假设你字面意思写了sub的定义,而你字面意思写了$private=False

    此外,那个:

    $private=False 调用 'named' 仍会打印 'Official business!'而我认为不应该产生任何输出。

    表示在所有情况下都有一些输出。

    Anyhoo,所有这些事情怎么可能同时为真?


    这些是编译时错误:

    sub named( :official( $private = True ) )   { "Official business!" if $private }
    sub named( :official( $private = False ) )  { "Official business!" if $private }
    

    是这样的:

    $private = False;
    

    除非之前有my $private...

    还有这个:

    sub named( :official( $private ) ) {
      $private = True;
      "Official business!" if $private
    }
    named;
    

    产生Cannot assign to a readonly variable or a value(当前在运行时),因为默认情况下,例程的参数是只读的。


    你还说有输出(表面上是Official business!,但有时可能是别的东西,例如()?)。

    您没有提到用于显示输出的say 或类似例程。怎么可能?让我们介绍一个say


    所以,把这些东西放在一起,应用椒盐卷饼的逻辑,我到了这里:

    sub named(:official($private)) { "Official business!" if $private }
    my $private;
    $private = False;
    say named :official;         # Official business!
    say named :!official;        # ()
    say named official => False; # ()
    say named :official(False);  # ()
    say named;                   # ()
    

    解谜的解释:

    • () 不是没有输出”。所以这与你的 Q 叙述并不矛盾。

    • 我们已经写了$private = False。由于词法作用域,它对代码没有影响,但我们确实编写了它。 :)


    我暖和吗?

    【讨论】:

      【解决方案4】:

      亲爱的善良和慷慨的乐民,

      感谢您的回复和讨论。之后我现在明白了我不明白的东西。我误解的根源从这里开始:在撰写本文时,the doc page for class Pair 说:

      创建对的语法有很多

      并继续举例,其中之一是这一行:

      :foo(127) # foo 的缩写 => 127

      所以我在 raku 交互环境中想到了这两行:

      > :foo(127)
      foo => 127
      > :foo.kv
      (foo True)
      

      最后一行回答(foo 127)。不过很遗憾,不,答案是(foo True)

      但是当我去阅读“类签名”页面并与示例陷入困境时,我不知道:

      sub named(:official($private));
      named :official
      

      现在看来是一个截断的例子。

      让我觉得冒号可以做的事情有很多魔力。

      不管怎样,希望大家都好好的……鳄鱼们以后见。

      【讨论】:

      • 1) “会在最后一行回答 (foo 127)。”那是因为 :foo 只是 :foo(True)foo => True 的简写。如果你想要(foo 127),那么你必须明确指定其他值,即:foo(127).kv #=> (foo 127)。我认为像 :foo 这样的对默认为布尔值使这些对非常适合布尔标志(例如,send-message 'hello!', :verbose, :header)。 2)“……稍后见鳄鱼。” Rakoons 可能是 Rakus 人的一个更酷的绰号;-)(感谢 lizmat 创造了这个词!)