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:

has @.items[3] is rw = 'Mince Pie', 'White Wine', 'Stinky Cheese';
The output is then:
===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.


In reply to [Raku] Assigning defaults to attributes that are fixed length lists (and other confusions) by tomgracey

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.