Why can readonly array attributes be modified on a Raku class, but on the other hand, scalars cannot be modified?
How can I make @.baz
"readonly"?
class Boo {
has $.bar;
has @.baz;
};
my $boo = Boo.new;
$boo.baz = (1, 2); # works ... ?
say $boo.baz;
$boo.bar = 1; #fails ... expected
My rakudo version:
This is Rakudo version 2020.05.1 built on MoarVM version 2020.05
implementing Raku 6.d.
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With