raku is a well behaved language in that concepts are kept "orthogonal" where possible. So from
the docs there are three concepts in play:
- the sigil - @ (or $, %, &)- provides guidance on the content of your attribute container - in the case of @ it does role Positional
- the twigil - . or ! - provides guidance on the encapsulation, a "public attribute" with '.' has a getter accessor method automatically generated - with 'is rw' both getter and setter methods are provided
- the actual contents - in this case an Array - and each item in an Array is a scalar container that may be assigned a value
You are experiencing the implications of this design in a number of ways:
- the twigil and is rw trait apply at the attribute container level - so you can assign an entirely different Array to your attribute if it is marked 'is rw', regardless of this, when you have the Array (even if the container is read only) individual items are still read/write and may be assigned values, sliced, pushed/popped (unless a where constraint or type subset is provided) - you can assign a List if you want immutability
- the generated accessor method therefore applies at the top level - and, as with $ scalars, the setter method provides an lvalue that can be assigned to with the '=' operator so $fish.scales = ('green','blue','yellow'); is fine
- raku public attributes are (deliberately) simple - so that is all you get from the '.' twigil ... I think that the idea is to make raku OO be very lightweight in the role of random data structure, but to have encapsulation also be very light and to kick in for all use cases that have even just the slightest type management demands - the colon formulation of the method call is awesome for this $fish.scales: ('green','blue','yellow');
1 class Fish {
2 has @!scales;
3
4 multi method scales { @!scales }
5 multi method scales( @new ) { @!scales = @new }
6 method raku { "[ scales => {@!scales} ]" }
7 }
8
9 my $fish = Fish.new;
10 $fish.scales: ('green','blue','yellow');
11
12 dd $fish;