这段代码:
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错误消息的情况,还是我缺少的一些容器魔术在起作用?
这段代码:
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错误消息的情况,还是某种容器魔术在起作用?
这是一个很好的问题,我不会尝试回答。