这段代码:
constant %what = { doesn't => 'change' };
%what = { will => "change" }
应该说一些类似于“无法修改不可变哈希”的内容。
谁这么说的?我的意思是修辞性的,而不是粗鲁的。我明白了why你是这么认为的,但重要的是要小心使用“应该”这个词,因为它意味着某些权威是这么说的,例如规范、设计文档、某人的常识或其他什么。
根据当前规范和 Rakudo 实施,什么constant foo ...
确实是永久地(持续地)bind foo
到某个特定的“价值”。
如果该“值”是一个容器,那么foo
不断引用该容器。 (是的,容器可以是“值”,对于此处合适的“值”的某些定义。)
所以你上面的代码已经改变了包含的元素within那个容器,也就是说,根据规格,完美的 cromulent:
say %what; # {will => change}
与此同时,警告消息合理地提到了哈希构造函数的无用使用,并指出:
did you mean := instead?
如果你尝试这样做:
constant %what = { doesn't => 'change' };
%what := { will => "change" }
You get:
Cannot use bind operator with this left-hand side
因为,正如已经确定的那样,%what
是一个编译时间常数永久绑定到在编译时创建和初始化的哈希,以及该方面——永久绑定%what
到该特定的哈希值——在此程序运行期间无法更改。
Positional
s 有几乎相同的问题,但错误不同。在这种情况下,它是关于不能修改不可变的,但是Str
:
constant @what = <does not change>;
@what = <does change> # Cannot modify an immutable Str (does)
这有点不同。 Aconstant
声明绑定,无论你是否写=
or :=
。所以常量声明等价于:
constant %what := { doesn't => 'change' }
constant @what := <does not change>;
第一行绑定%what
to { doesn't => 'change' }
这是一个可变的Hash
.
第二行绑定@what
to <does not change>
这是一个不可变的List
.
你可以这样写:
constant @what = [<does not change>];
@what = <does change>;
say @what; # [does change]
A Scalar
按预期工作。
不完全的。
A scalar(小写,通用术语)的作用是:
constant $scalar = 42;
$scalar = 99; # Cannot assign to an immutable value
记住这一点constant
always binds,上面的代码类似:
my $scalar := 42;
$scalar = 99; # Cannot assign to an immutable value
But a Scalar https://docs.raku.org/type/Scalar与此上下文中的其他容器的工作方式相同:
constant $scalar = $ = 42;
$scalar = 99; # OK
(除非你想惹恼别人,否则不要编写这样的代码。)
这是 LTA 错误消息的情况,还是某种容器魔法在起作用?
这是一个很好的问题,我不会尝试回答这个问题。