As @choroba's reply notes, your code actually throws an error in Perl 6.c.
The error occurs on the second iteration, when only 5, 6
is left from the input array, which can't be mapped to the signature $a, $b, $c, $d
because all four parameters in that signature are mandatory.
There are multiple ways to make it work:
A) Mark the parameters as optional.
for @arr -> $a, $b?, $c?, $d? {
say "---";
say $a;
say $b if $b.defined;
say $c if $c.defined;
say $d if $d.defined;
}
The ?
means optional – i.e. when no argument is passed to that parameter, it's set to the value Mu
("most undefined"). Note that there's no need to mark the first parameter as optional, because when there are zero input elements left the for
loop terminates and doesn't try to enter another iteration.
Output:
---
1
2
3
4
---
5
6
B) Specify defaults for the parameters.
for @arr -> $a, $b = 'default-B', $c = 'default-C', $d = 'default-D' {
say ($a, $b, $c, $d);
}
This is what @choroba already suggested. It's essentially another way of making the parameters optional, but now with a custom value instead of Mu
in case no argument was passed to them.
Output:
(1 2 3 4)
(5 6 default-C default-D)
C) Use .rotor
to handle the partitioning.
Using a for
block with a multi-parameter signature is not the only way to iterate a list of values n-at-a-time. The .rotor
method provides the same functionality in a more functional style. It skips partial iterations at the end by default, so you need to give it the :partial
option to include that iteration:
for @arr.rotor(4, :partial) -> @slice {
say @slice;
}
For each iteration, @slice
becomes a List of 4 elements, except for the last iteration where it can have fewer elements.. (You could check @slice.elems
inside the loop body to see how many you got.)
Output:
(1 2 3 4)
(5 6)