Home > Mobile >  Inconsistent behavior when coercing an Array to a List?
Inconsistent behavior when coercing an Array to a List?

Time:11-09

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?

CodePudding user response:

In the @ sigil, documentation states

By default, when you assign a List to an @-sigiled variable, you create an Array.

"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)
  • Related