为什么我的%h是List = 1,2; 有效的作业?

cod*_*ons 8 containers variable-assignment rakudo raku

在完成我即将发布的关于 sigils 的 Raku Advent Calendar 帖子时,我决定仔细检查我对 sigils 创建的类型约束的理解。文档使用下表描述了印记类型约束\n:

\n\n

根据这张表(以及我对印记和容器如何工作的一般理解),我强烈期望这段代码

\n
my %percent-sigil is List = 1,2;\nmy @at-sigil is Map = :k<v>;\n
Run Code Online (Sandbox Code Playgroud)\n

抛出错误。

\n

具体来说,我预计is List会尝试将 -sigiled 变量绑定%到 a List,并且这会抛出X::TypeCheck::Binding错误 \xe2\x80\x93 ,与抛出的错误相同my %h := 1,2

\n

但它并没有出错。第一行创建的 aList除了其变量上的印记之外,在各方面看起来都非常普通。第二个创建了一个看似正常的Map。他们俩都没有秘密的Scalar中间人,至少据我通过VAR类似的内省得知。

\n

我快速浏览了World.nqp 源代码%,并且丢弃类型约束似乎is List是预期的行为。

\n

那么,这种行为是否正确/有意?如果是这样,为什么?这如何与 sigils 通常提供的类型约束和其他保证相适应?

\n

(我必须承认,看到一个%不支持关联索引的 -sigiled 变量让我感到震惊\xe2\x80\xa6)

\n

Eli*_*sen 5

我认为这是一个灰色地带,介于 DIHWIDT(Docter,当我这样做时会很受伤)和实施过程中的监督之间。

事实是,您可以创建自己的类并在is特征中使用它。Hash基本上,这会覆盖从默认值(for %) 和Array(for @sigils)创建对象所使用的类型。只要您提供接口方法,它(当前)就可以工作。例如:

class Foo {
    method AT-KEY($) { 42 }
}
my %h is Foo;
say %h<a>;  # 42
Run Code Online (Sandbox Code Playgroud)

但是,如果您想将这样的对象作为参数传递给%签名中带有印记的 sub,它将失败,因为该类没有消耗该Associatve角色:

sub bar(%) { 666 }
say bar(%h);
===SORRY!=== Error while compiling -e
Calling bar(A) will never work with declared signature (%)
Run Code Online (Sandbox Code Playgroud)

我不确定为什么在编译时不使用该特征强制执行Associative(for the %sigil) 和Positional(for ) 的测试。我认为这是一个疏忽,也许需要在 6.e 中修复。@is

  • 另外,我更担心您**不**提供接口方法但声明仍然有效的情况。如果我删除“AT-KEY”方法,我仍然可以声明“my %h is Foo”而不会出现任何错误。%h&lt;a&gt; 抛出一个错误,但这更糟糕(imo)——“Raku,%-sigiled 变量不支持关联索引是什么意思!” (2认同)