tomgracey has asked for the wisdom of the Perl Monks concerning the following question:
Hello Monks
After some consideration I've decided to continue posting my Raku questions on perlmonks. It is tempting to just go directly to the Raku IRC channel, however then the question/answer doesn't get recorded and thereby potentially help someone else out. When I was getting to grips with Perl I rarely needed to ask questions as I could nearly always find someone who had already posted a similar problem. With Raku searching doesn't seem to bring up so many Q and A type threads. No doubt much of this is due to it being so new, but I can't wondering if encouraging people to resolve problems via chat is actually that helpful. I don't know. Could be wrong. Just what immediately springs to mind. (Of course there is stackoverflow, but lets just say I am not such a great fan of their moderation methodology)
Anyway the show must go on, so here is my question:
Lets say I have the following (contrived) code:
class Hamper { has $.name = 'Christmas Basket'; has @.items is rw = 'Mince Pie', 'White Wine', 'Stinky Cheese' +; } my $hamper = Hamper.new; say "Name: " ~ $hamper.name; say "Items: " ~ $hamper.items;
This works as expected (that is I expect!), spitting out
Name: Christmas Basket Items: Mince Pie White Wine Stinky Cheese
However, say I want to limit the size of @!items to 3 elements. That is, I want the code to fall over with an error if I try to put 4 elements into it. And this is where I'm already not sure if I'm even going about it in the right way in the first place. My understanding (mentioned in the docs, and also e.g this post) is that I ought to be able to limit the size of the "positional" by changing the line which defines @.items to:
The output is then:has @.items[3] is rw = 'Mince Pie', 'White Wine', 'Stinky Cheese';
===SORRY!=== Error while compiling /path/script.raku Defaults on compound attribute types not yet implemented. Sorry. Workaround: Create/Adapt TWEAK method in class Hamper, e.g: method TWEAK() { @!items := (initial values) unless @!items; } at /path/script.raku:3
I assume this to mean I created my fixed length positional successfully, but need to assign defaults separately because the compiler has not yet been trained on this particular scenario. Fair enough. So I do literally as the error message recommends, adding in the TWEAK method. My code now reads:
class Hamper { has $.name = 'Christmas Basket'; has @.items[3] is rw; method TWEAK(){ @!items := 'Mince Pie', 'White Wine', 'Stinky Cheese' unless @ +!items; } } my $hamper = Hamper.new; say "Name: " ~ $hamper.name; say "Items: " ~ $hamper.items;
Now the output is
Name: Christmas Basket Use of uninitialized value element[0] 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 script.raku line 16 Use of uninitialized value element[1] 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 script.raku line 16 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 script.raku line 16 Items:
Yuck! The defaults for @!items do not appear to get assigned. But if I remove unless @!items then I get:
Name: Christmas Basket Items: Mince Pie White Wine Stinky Cheese
as desired. But now the "defaults" overwrite any user specified values. E.g. if I change the my $hamper line to be
my $hamper = Hamper.new( items => ('Dog', 'Cat', 'Sausage') );
The output without the unless @!items is still
Name: Christmas Basket Items: Mince Pie White Wine Stinky Cheese
which is not what anyone would want. So is that error message bad advice - or otherwise what is happening? Why is it that unless @!items seems to be triggered when @!items is surely empty?
Unfortunately I'm nowhere near done yet!
Say I keep the line which assigns the "defaults", without the unless @!items - ie accepting (for the time being) it writes over user specified values
What happens if I try to assign more than 3 values to @!items?
method TWEAK(){ @!items := ('Mince Pie', 'White Wine', 'Stinky Cheese', 'Sardines' +, 'Dogfood'); }
The output is then:
Name: Christmas Basket Items: Mince Pie White Wine Stinky Cheese Sardines Dogfood
Yup.. it appears to completely ignore the 3 element limit that (I believed) was placed on @!items. Shouldn't it be falling over? What is with that? (Ok as I write this I think I can hazard a guess - the answer is going to be something along the lines of "the fixed limit restriction applies to the accessor and not to the underlying attribute, and since in TWEAK you are accessing the attribute directly the restriction is circumvented." Fine if this is the case...
But final thing. My @!items are all strings. Say I want to etch that in stone:
has Str @.items[3];
(At least, I am under the impression that Str used in that context should apply a restriction to the elements of @.items... or did I get that wrong?)
So now my code looks like this:
class Hamper { has $.name = 'Christmas Basket'; has Str @.items[3] is rw; method TWEAK(){ @!items := ('Mince Pie', 'White Wine', 'Stinky Cheese'); } } my $hamper = Hamper.new; say "Name: " ~ $hamper.name; say "Items: " ~ $hamper.items;
And drumroll for the output...
Type check failed in binding; expected Positional[Str] but got List (( +"Mince Pie", "White...) in method TWEAK at script.raku line 9 in block <unit> at script.raku line 13
So what's going on there? Did I inadvertently define a 3 character string/some other weird entity? I realise the vagueness of my understanding of what a 'Positional' vs 'List' and/or 'Array' may be the bottleneck here.
I guess this is very rambling way of simply asking, "In Raku, how do you define an object attribute that is a fixed length list with typed elements, and assign defaults to it?" However, I thought I'd post in tedious detail in the hope of rectifying all aspects of my confusion.
Thanks for reading this far. You should think about going on holiday. You deserve it.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: [Raku] Assigning defaults to attributes that are fixed length lists (and other confusions)
by duelafn (Parson) on Apr 28, 2021 at 13:01 UTC | |
by tomgracey (Scribe) on Apr 28, 2021 at 20:00 UTC | |
by tomgracey (Scribe) on Apr 29, 2021 at 15:53 UTC | |
by p6steve (Sexton) on May 03, 2021 at 22:30 UTC | |
by jcb (Parson) on May 05, 2021 at 21:33 UTC |