【问题标题】:Destructuring/list assignment with the `has` declarator使用 `has` 声明符进行解构/列表分配
【发布时间】:2025-12-09 14:30:02
【问题描述】:

[我同时遇到了提示这个问题的问题和我的previous question,但认为这两个问题应该分开。]

文档描述了将destructuring assignmentmyour 变量一起使用,但没有提及它是否可以与has 变量一起使用。但是 Raku 足够稳定,我决定尝试一下,而且它似乎起作用了:

class C { has $.a; has $.b }
class D { has ($.a, $.b) }
C.new: :a<foo>;  # OUTPUT: «C.new(a => "foo", b => Any)»
D.new: :a<foo>;  # OUTPUT: «D.new(a => "foo", b => Any)»

但是,这种形式似乎破坏了属性默认值:

class C { has $.a; has $.b = 42 }
class D { has ($.a, $.b = 42) }
C.new: :a<foo>;  # OUTPUT: «C.new(a => "foo", b => 42)»
D.new: :a<foo>;  # OUTPUT: «C.new(a => "foo", b => Any)»

此外,翻转默认位置会提供一条错误消息,可能会了解正在发生的事情(尽管不足以让我了解上述行为是否正确)。 p>

class D { has ($.a = 42, $.b) }
# OUTPUT:
===SORRY!=== Error while compiling:
Cannot put required parameter $.b after optional parameters

所以,有几个问题:解构赋值是否应该has一起工作?如果是这样,默认值的行为是否正确/有没有办法在使用解构赋值时分配默认值?

(我真的希望 has 支持解构赋值 并且可以使用默认值;即使对于使用真正 OO 的类的人来说,这似乎是一个小众功能, 非常对于编写更多功能代码的人来说非常方便,他们希望将类用作具有固定键的稍微更类型安全的哈希。能够编写像class User { has (Str $.first-name, Str $.last-name, Int $.age) } 这样的东西非常 对那种代码很有帮助)

【问题讨论】:

    标签: constructor variable-assignment raku destructuring rakudo


    【解决方案1】:

    目前这是 Rakudo 中的 known bughas 的预期行为是支持 list assignment,这将使语法与问题中显示的非常相似。

    我不确定是否支持的语法是:

    class D { has ($.a, $.b = 42) }
    D.new: :a<foo>;  # OUTPUT: «D.new(a => "foo", b => 42)»
    

    class D { has ($.a, $.b) = (Any, 42) }
    D.new: :a<foo>;  # OUTPUT: «D.new(a => "foo", b => 42)»
    

    但是,无论哪种方式,都有一种方法可以使用单个 has 来声明多个属性,同时还为这些属性提供默认值。

    目前的预期是这个错误会在RakuAST 分支合并后的某个时间得到解决。

    【讨论】: