my @foo;
@foo = (1, (2, 3), (4, (5, 6), 7), (8), 9).List;
say @foo.flat;
# OUTPUT: (1 (2 3) (4 (5 6) 7) 8 9)
# this is NOT the output I expected.
@foo = (1, (2, 3), (4, (5, 6), 7), (8), 9);
say @foo.List.flat;
# OUTPUT: (1 2 3 4 5 6 7 8 9)
# this is the output I expected.
say $*DISTRO; # macos (12.6)
say $*VM; # moar (2022.07)
say $*RAKU; # Raku (6.d)
say $*KERNEL; # darwin
It seems that coercing in the assignment has no effect.
Why does it matter when @foo is coerced to a List?
In the @ sigil, documentation states
By default, when you assign a
List
to an @-sigiled variable, you create anArray
.
"assign" there refers to =
, and RHS need not be List actually; after my @f = ...
, @f
ends up of the type Array. (In your case RHS happens to be a List; in fact, it's a List already with the literal so you don't need .List
there).
Now, since @foo
is an Array, it puts its elements in scalar containers, which resist against flattening, hence the behaviour you see.
>>> my @foo = (1, (2, 3), (4, (5, 6), 7), (8), 9)
[1 (2 3) (4 (5 6) 7) 8 9]
>>> @foo.WHAT
(Array)
>>> @foo.flat
(1 (2 3) (4 (5 6) 7) 8 9)
As mentioned in the first link, you can get @foo
as a List if you do my @foo := ...
instead, i.e., via binding, or overriding the default type on Positionals explicitly, i.e., my @foo is List = ...
(or by changing the sigil, e.g., my $foo := ...
...).
As for the second case, @foo.List
makes a new List object out of @foo
; so no scalar container, yes full flattening:
>>> @foo.List
(1 (2 3) (4 (5 6) 7) 8 9)
>>> @foo.List.WHAT
(List)
>>> @foo.List.flat
(1 2 3 4 5 6 7 8 9)