During multi-value iteration, if we run out of values, the last group of values will not be handled in the current version of Rakudo.
my @arr = 1, 2, 3, 4, 5, 6
for @arr -> $a, $b, $c, $d {
say $a
say $b
say $c
say $d
}
The result is
1
2
3
4
, which drops 5
and 6
.
So in which way I am able get the elements that are dropped?
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:
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
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)
.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)
Trying in Rakudo Star I've just installed:
===SORRY!=== Error while compiling /home/choroba/1.p6
Unexpected block in infix position (missing statement control word before the expression?)
at /home/choroba/1.p6:2
------> for @arr⏏ -> $a, $b, $c, $d {
expecting any of:
infix
infix stopper
After adding semicolons everywhere, I'm getting
1
2
3
4
Too few positionals passed; expected 4 arguments but got 2
in block <unit> at /home/choroba/1.p6 line 2
You can provide default values if you don't want to get an error:
for @arr -> $a,
$b = 'Missing b',
$c = 'Missing c',
$d = 'Missing d' {
As smls comments, you can also make the variables optional:
for @arr -> $a, $b?, $c?, $d? {
which will work the same as using $var = Mu
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With