4

I am trying to put the parameters in a for loop into array of FIXED size. This is what I have been doing (I want to use a array @m of 3 elements):

for (1..19).rotor(3, :partial) -> @m { say @m; } # works, but I cannot specify size of @m

However, all of the following give me errors:

for (1..19).rotor(3, :partial) -> @m[0,1,2] { say @m; }
===SORRY!=== Error while compiling:
Variable '@m' is not declared
------> ).rotor(3, :partial) -> @m[0,1,2] { say ⏏@m; }

for (1..19).rotor(3 => -2) -> @m[0..2] { say @m; }
===SORRY!=== Error while compiling:
Variable '@m' is not declared
------> 1..19).rotor(3 => -2) -> @m[0..2] { say ⏏@m; }

for (1..19).rotor(3 => -2) -> @m[3] { say $_; say @m; }
===SORRY!=== Error while compiling:
Variable '@m' is not declared
------> ).rotor(3 => -2) -> @m[3] { say $_; say ⏏@m; }

So, how should I specify that the array @m must have only 3 elements?

halfer
  • 19,824
  • 17
  • 99
  • 186
lisprogtor
  • 5,677
  • 11
  • 17
  • Hi lisprogtor. There is a preference here for posts not being signed, and for a general brevity of style. Could I trouble you to refrain from adding these? – halfer Apr 13 '20 at 10:43
  • I often advise the following: _Note that we prefer a technical style of writing here. We gently discourage greetings, hope-you-can-helps, thanks, advance thanks, notes of appreciation, regards, kind regards, signatures, please-can-you-helps, chatty material and abbreviated txtspk, pleading, how long you've been stuck, voting advice, meta commentary, etc. Just explain your problem, and show what you've tried, what you expected, and what actually happened._ – halfer Apr 13 '20 at 10:43
  • Is it NOT even okay to be polite here? – lisprogtor Apr 19 '20 at 05:37
  • It's not a question of politeness; it's a question of technical writing. [This discussion](https://meta.stackoverflow.com/q/260776) is probably the canonical one. [This discussion](https://meta.stackoverflow.com/q/266525) covers similar ground from people desiring to express politeness. The short answer is these these discussions have been had before, and there has been a settlement on preferring brevity. You can get involved in these discussions yourself if you would rather the community changed course. – halfer Apr 19 '20 at 09:58
  • By and large (volunteer) editors amend questions with these guidelines in mind, and they are very grateful when community members make small adjustments to their personal style, in order that new editing work is not created. – halfer Apr 19 '20 at 09:59

2 Answers2

5

The title of the question mentions destructuring, but that is about taking something apart. For example, we could extract the three elements using it:

for (1..19).rotor(3, :partial) -> [$a, $b, $c] {
}

However, this doesn't seem to actually be a destructuring problem, since the request isn't to break the passed aggregate into its parts, but transform it into a different type of aggregate.

Looking a little further at the question:

I am trying to put the parameters in a for loop into array of FIXED size.

The thing is, rotor doesn't produce (mutable) Arrays at all. Instead, when writing:

for (1..19).rotor(3, :partial) -> @m {
}

Then @m is a List. A List is immutable (and thus implicitly its size is fixed at creation), so if the intent is that there can be no accidental change of size, that's already a cert. Unfortunately, the ultimate goal wasn't stated.

If really wanting to turn the passed immutable List into a shaped Array, there's nothing for it other than to assign it into a new fixed size Array:

for (1..19).rotor(3, :partial) -> @l {
    my @arr[3] = @l;
}

Of course, this is going to blow up if the :partial leads to leftover elements; one could do:

for (1..19).rotor(3, :partial) -> @l {
    my @arr[@l.elems] = @l;
}

To avoid that. However, if the goal as really to ensure that things blow up if there ever are leftover elems, then either a where:

for (1..19).rotor(3, :partial) -> @m where .elems == 3 {
}

Or, a bit less clearly, a throw-away destructure:

for (1..19).rotor(3, :partial) -> @m [$,$,$] {
}

Would do it.

Jonathan Worthington
  • 29,104
  • 2
  • 97
  • 136
  • Thank you very much Jonathan Worthington for your help !!! The throw-away destructure is new to me and I will look more into it. Thanks !!! – lisprogtor Apr 09 '20 at 06:24
2

So the -> @m[3] is what you want but that's assigning a Signature your anonymous block that's expecting a shaped array and you're passing in a List.

So what I ended up doing may coercing my list into a shaped Array.

for (1..19).rotor(3, :partial).map( { Array.new(:shape(3),$_ ) } ) -> @m[3] { say @m; }

And then it works fine. There's probably a better way to do it though.

Scimon Proctor
  • 4,558
  • 23
  • 22