无用的哈希编写器,还是不能修改不可变的哈希?

jjm*_*elo 4 perl6

这段代码:

constant %what = { doesn't => 'change' }; 
%what = { will => "change" } 
Run Code Online (Sandbox Code Playgroud)

应该说“不能修改不可变的哈希”。但是,它说:

Potential difficulties:
Useless use of hash composer on right side of hash assignment; did you mean := instead?
Run Code Online (Sandbox Code Playgroud)

Positionals有几乎相同的问题,但错误有所不同。在这种情况下,它不能修改不可变的,而只能修改一个Str:

constant @what = <does not change>;
@what = <does change> # Cannot modify an immutable Str (does)
Run Code Online (Sandbox Code Playgroud)

标量工作正常。这是LTA错误消息的情况,还是我缺少的一些容器魔术在起作用?

rai*_*iph 7

这段代码:

constant %what = { doesn't => 'change' }; 
%what = { will => "change" } 
Run Code Online (Sandbox Code Playgroud)

应该说“不能修改不可变的哈希”。

谁这么说 我的意思是修辞,而不是粗鲁的。我明白为什么这样认为,但是使用“应该”一词时要小心,因为这意味着某些权威机构应该这样说,例如规范或设计文档或某人的常识或...,这一点很重要。

根据当前的规范以及Rakudo的实现,在程序运行期间,不断使某些特定的“值” constant foo成为foo参考。如果该“值”是一个容器,则foo始终引用该容器。(是的,对于“值”的某些定义,容器可以是“值”。)

因此,您上面的代码愉快地更改该容器的内容

say %what; # {will => change}
Run Code Online (Sandbox Code Playgroud)

同时,警告消息合理地提到了对哈希构造函数的无用使用,此外还指出:

did you mean := instead?
Run Code Online (Sandbox Code Playgroud)

如果您尝试这样做:

constant %what = { doesn't => 'change' }; 
%what := { will => "change" }
Run Code Online (Sandbox Code Playgroud)

你得到:

Cannot use bind operator with this left-hand side
Run Code Online (Sandbox Code Playgroud)

因为,正如已经确定的那样,%what是一个绑定到在编译时创建和初始化的哈希的编译时常量,并且%what在此程序运行期间不能更改该方面(与特定哈希的绑定)。

Positionals有几乎相同的问题,但错误有所不同。在这种情况下,它不能修改不可变的,而只能修改一个Str:

constant @what = <does not change>;
@what = <does change> # Cannot modify an immutable Str (does)
Run Code Online (Sandbox Code Playgroud)

有点不同。一个constant声明结合,无论你写=:=。因此,第一行等效于:

constant @what := <does not change>;
Run Code Online (Sandbox Code Playgroud)

这可能更清楚地显示正在发生的事情。@默认情况下,该符号会创建一个Array。但是,如果您绑定到,List则它也将绑定到List。A List是不可变的。因此,下一行变为:

@what = <does change> # Cannot modify an immutable Str (does)
Run Code Online (Sandbox Code Playgroud)

您可以改写:

constant @what = [<does not change>];
@what = <does change>;
say @what; # [does change]
Run Code Online (Sandbox Code Playgroud)

一个Scalar按预期工作。

这是因为它不是Scalar。相反,您将谈论标量,例如标量Int

my $foo = 42;       say $foo.VAR.^name;  # Scalar
constant $bar = 42; say $bar.VAR.^name;  # Int
Run Code Online (Sandbox Code Playgroud)

右侧提到非匿名将Scalar产生其包含的值。相反,任何在右侧提到复合容器的人都会引用该容器。

匿名者Scalar还会产生对该容器的引用,而不是其值:

constant $foo = $;
$foo = 42;
say $foo; # 42
Run Code Online (Sandbox Code Playgroud)

这是LTA错误消息的情况,还是某种容器魔术在起作用?

这是一个很好的问题,我不会尝试回答。