Hi Tom... with you on the SO tone ... here's what I think is going on:
- An empty Array is falsey, yet an empty shaped Array is truthy (I would be interested to know why!) - thus, as you have already noted, the original error message is wrong in the suggestion for TWEAK. (You may wish to raise a bug issue at rakudostar on git.) More at https://stackoverflow.com/questions/67373726
- You are getting a compiler warning from trying to say ~$hamper.items where there is an empty value (Any) in a shaped Array... this does not happen with a non-shaped Array as the length auto-adjusts to the contents.
Use of uninitialized value element[2] of type Any in string context.
Methods .^name, .raku, .gist, or .say can be used to stringify it to s
+omething meaningful.
in block <unit> at test.raku line 14
So, I propose you implement a Str method to bypass (Any) elements and format the object output for .put (or say ~$hamper).
- Array elements are each scalar containers and are each rw in any case - has @.items is rw just allows the top level array to be assigned to via a generated setter method. (NB. TWEAK can use the private @!items variable directly to assign the defaults).
- You can see this now gives low boilerplate accessors that do what you want (?) and protect from writing beyond 3 elements.
class Hamper {
has $.name = 'Christmas Basket';
has @.items[3];
method TWEAK {
@!items = ['Mince Pie', 'White Wine', 'Stinky Cheese'] unless
+@!items.any.so;
}
method Str {
"Name: {$!name}\nItems: [{@!items.grep(*.so).join(', ')}]\n";
}
}
given Hamper.new {
.items[2] = 'Hard Cheese';
.put;
}
#Name: Christmas Basket
#Items: [Mince Pie, White Wine, Hard Cheese]
given Hamper.new( items => ['Fish', 'Canoe'] ) {
.put;
.items[2] = 'Bicycle';
.put;
#.items[3] = 'Horse'; #fails.. Index 3 for dimension 1 out of
+range (must be 0..2)
#.items.push: 'Blue Nun'; #fails.. Cannot push a fixed-dimension a
+rray
}
#Name: Christmas Basket
#Items: [Fish, Canoe]
#Name: Christmas Basket
#Items: [Fish, Canoe, Bicycle]