Why can readonly array attributes on a Raku class be modified?
The baz
attribute is read only.
The thing is that the baz
attribute is an Array
which has mutable elements.
When you call $boo.baz
you basically get a reference to the array.
Once you have a reference to the array you can do anything that you could normally do to the array.
say $boo.baz.VAR.name; # @!baz
When you assign to an array, what you are really doing is telling the array that it will have new contents.
my @a = ('a','b','c');
say @a.WHICH; # Array|94070988080608
@a = (1, 2, 3);
say @a.WHICH; # Array|94070988080608
Notice that the .WHICH
doesn't change. That is because it is still the same array. It just has new contents.
The exact same thing happens when you assign to a public array attribute.
You are not assigning a new array, you are altering the existing one.
All of the behaviours of a variable are not intrinsic to the variable, they are instead handled by an object.
In the case of arrays the object that handles the assignment is Array
.
The simplest fix is to just overload the autogenerated accessor method.
class Boo {
has $.bar;
has @.baz;
method baz () { @!baz.List }
}
If you never plan on changing the values in @!baz you could make it a List itself
class Boo {
has $.bar;
has @.baz is List;
}