Assignment to nested lists in Perl 6
There's nothing wrong (that is, ordinary assignment in P6 is designed to do as it has done) but at a guess you were hoping that making the structure on the two sides the same would result in $a
getting 1
, $b
getting 2
and $c
getting 3
.
For that, you want "binding assignment" (aka just "binding"), not ordinary assignment:
my ($a, $b, $c);
:(($a, $b), $c) := ((1, 2), 3);
Note the colon before the list on the left, making it a signature literal, and the colon before the =
, making it a binding operation.
If you want to have the result be 1, 2, 3
, you must Slip
the list:
my ($a, $b, $c) = |(1, 2), 3;
This is a consequence of the single argument rule: https://docs.raku.org/type/Signature#Single_Argument_Rule_Slurpy
This is also why this just works:
my ($a, $b, $c) = (1, 2, 3);
Even though (1,2,3)
is a List
with 3 elements, it will be auto-slipped because of the same single argument rule. You can of course also just remove the (superstitious) parentheses:
my ($a, $b, $c) = 1, 2, 3;
You are asking *What's wrong here", and I would say some variant of the single argument rule is at work. Since parentheses are only used here for grouping, what's going on is this assignment
($a, $b), $c = (1, 2), 3
(1, 2), 3
are behaving as a single argument, so they are slurpily assigned to the first element in your group, $a, $b
. Thus they get it all, and por old $c
only gets Any. Look at it this way:
my ($a, $b, $c);
($a, ($b, $c)) = ((1, 2), 3, 'þ');
say $a, $c; # OUTPUT: «(1 2)þ»
You might want to look at this code by Larry Wall, which uses »=«
, which does exactly what you are looking for. It's not documented, so you might want to wait a bit until it is.