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.

Tags:

Raku