arrayslistrakucoerce

Inconsistent behavior when coercing an Array to a List?


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?


Solution

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