Search code examples
arrayshashmapsequencepushraku

Why is this Raku program producing a Seq of Array rather than a simple Array?


my %f;
for $*HOME.dir() -> $file {
    my $filename = $file.basename;
    %f{$filename}.push: $file, rand;
}
my $p = %f.pick; # just need any old random element
say $p.^name;
say "{$p.values.^name} has {$p.values.elems} elements";
say "{$p.values[0].^name} has {$p.values[0].elems} elements";

say '';
say $*RAKU;
say $*DISTRO;
say $*KERNEL;
say $*VM;

Output:

Pair
Seq has 1 elements
Array has 2 elements

Raku (6.d)
macos (13.2.1)
darwin
moar (2023.02)

Why is the .values of $p a Seq of Array, rather than a simple Array?


Solution

  • Why is the .values of %f a Seq of Array, rather than a simple Array?

    First, as @codesections has pointed out, it's not %f, it's a single element from %f (the "first" one, which is misleading, but that's a red herring).

    So it's the .values of a Pair.


    The doc for Pair.values says:

    multi method values(Pair:D: --> List:D)
    

    Returns a List containing the value of the invocant.

    The doc says it should be a List (neither a Seq nor an Array).

    Oops.


    The current .values method declaration in main/src/core.c/Pair.pm6 is:

    multi method values(Pair:D:) {
        Seq.new(Rakudo::Iterator.OneValue($!value))
    }
    

    So that's why you're getting a Seq.

    But should you be? Why does the actual result not match the doc? What needs to be fixed?


    One possibility is the doc has always been wrong. Git blame shows it was written in mid 2016. Was the doc once right but Rakudo changed?

    I joined the self-serve #whateverable IRC bot channel (using kiwiirc), and then entered:

    c: say (:a).values ~~ List
    

    That ran commitable6, one of a family of Raku IRC bots, to test what the result was of running that code on versions of the Rakudo compiler.

    A couple minutes later I got a report showing that Rakudo did indeed return a List -- until 2017.08.

    What happened in 2017.08?


    The git blame report for main/src/core.c/Pair.pm6 shows a Liz commit:

    Streamline the standard Seq methods on Pair

    • add dedicated .iterator
    • make sure that .keys/kv/values/pairs/antipairs produce a Seq instead of a List, just as they do on any other object.

    So that's why Rakudo changed so that Pair.values returns a Seq.

    I just checked, and the doc for Pairs.kv is also wrong, and I think it's best to presume the doc for .keys/kv/values/pairs/antipairs will all be wrong too.


    I hope to write up my conclusions this weekend, but will publish what I have so far.