9

为什么只读数组属性可以在 Raku 类上修改,而标量却不能修改?

我怎样才能使@.baz“只读”?

class Boo {
    has $.bar;
    has @.baz;
};

my $boo = Boo.new;

$boo.baz = (1, 2); # works ... ?
say $boo.baz;

$boo.bar = 1; #fails ... expected

我的乐道版本:

This is Rakudo version 2020.05.1 built on MoarVM version 2020.05
implementing Raku 6.d.
4

2 回答 2

8

baz属性是只读的。

问题是该baz属性是Array具有可变元素的。


当你打电话时,$boo.baz你基本上会得到对数组的引用。

一旦你有了对数组的引用,你就可以做任何你通常可以对数组做的事情。

say $boo.baz.VAR.name; # @!baz

当你分配给一个数组时,你真正做的是告诉数组它将有新的内容。

my @a = ('a','b','c');
say @a.WHICH; # Array|94070988080608

@a = (1, 2, 3);
say @a.WHICH; # Array|94070988080608

请注意.WHICH不会改变。那是因为它仍然是同一个数组。它只是有新的内容。

当您分配给公共数组属性时,会发生完全相同的事情。
您不是在分配新数组,而是在更改现有数组。

变量的所有行为都不是变量固有的,而是由对象处理。
在数组的情况下,处理赋值的对象是Array.


最简单的解决方法是重载自动生成的访问器方法。

class Boo {
    has $.bar;
    has @.baz;

    method baz () { @!baz.List }
}

如果您从不打算更改 @!baz 中的值,您可以将其设为 List 本身

class Boo {
    has $.bar;
    has @.baz is List;
}
于 2020-09-24T04:00:08.617 回答
0

我的投票投给了@BradGilbert 建议的 'is List' 版本......我使用默认值进行了尝试,并收到了这个很棒的错误消息:

===SORRY!=== Error while compiling ...
Defaults on compound attribute types not yet implemented. Sorry.
Workaround: Create/Adapt TWEAK method in class Boo, e.g:

    method TWEAK() {
        @!baz := (initial values) unless @!baz;
    }
于 2020-10-07T15:18:43.387 回答