- Is my assumption correct, or does it work differently?
Yes. Assignment flattens the left-hand side (LHS). Some additional reading:
- Is it possible to achieve destructuring behavior during assignment, similar to how it works with binding?
After a bit of research, I found this construction:
my ($a, @b, $c);
:($a is copy, @b, $c) := \(42, <a b c>, 42);
$a = 1;
say [$a, @b, $c]; # OUTPUTS: [1 (a b c) 42]
Although this is still technically binding, it behaves the way I wanted — I can reassign $a afterwards.
Unfortunately, this only works without any declarators. If we write:
my :($a is copy, @b, $c) := \(42, <a b c>, 42);
…it throws a Cannot assign to a readonly variable or a value exception when attempting to reassign $a.
Instead, we can use the is rw trait, but in that case, we need to provide a truly writable container, as the binding operator doesn’t create one itself:
my :($a is rw, @b, $c) := \(42.item, <a b c>, 42);
$a = 1;
say [$a, @b, $c]; # OUTPUTS: [1 (a b c) 42]
If some subroutine returns a list of values that we want to "assign" this way, .map(*.item) can help:
sub f { 42, <a b c>, 42 }
my :($a is rw, @b, $c) := f.map: *.item;
$a = 1;
say [$a, @b, $c]; # OUTPUTS: [1 (a b c) 42]