Search code examples
polymorphismraku

Raku signature (Array @r) is not (Array:D)?


I can not seem to make head or tails of this Raku error message I found while exploring grammars...


Cannot resolve caller report(Array:D); none of these signatures matches:
(Array @r)
(Match $r)

So an Array is not an Array?! How does that work and how do I find out why? Here is the full program and output.

#!/usr/bin/env perl6
use v6;
grammar Integers {
    rule TOP      { ^ .*? <targets> .* $  }
    rule targets  { <integer>+ % ',' }
    token integer { \d+ }
}

multi sub report(Array @r) { say @r.raku }
multi sub report(Match $r) { say $r.raku }

sub MAIN() {
    my $result = Integers.parse(' a 1234 ');
    report($result);
    report(%$result{'targets'});
    report(%$result{'targets'}{'integer'});
}
#`( output:
Match.new(:orig(" a 1234 "), :from(0), :pos(8), :hash(Map.new((:targets(Match.new(:orig(" a 1234 "), :from(3), :pos(8), :hash(Map.new((:integer([Match.new(:orig(" a 1234 "), :from(3), :pos(7))]))))))))))
Match.new(:orig(" a 1234 "), :from(3), :pos(8), :hash(Map.new((:integer([Match.new(:orig(" a 1234 "), :from(3), :pos(7))])))))
Cannot resolve caller report(Array:D); none of these signatures matches:
    (Array @r)
    (Match $r)
  in sub MAIN at /home/hans/Programming/Raku/Parsing/Array_Array.raku line 16
  in block <unit> at /home/hans/Programming/Raku/Parsing/Array_Array.raku line 3
)

Solution

  • You appear confused about the functionality of sigils and typing.

    When you use the @ sigil, you are implying a Positional constraint.

    sub foo(@a) { ... }
    

    will take anything that does the Positional role.

    foo( @b );
    foo( [1,2,3] );
    foo( (1,2,3) );
    

    When you specify a type with a @ in a signature, you're indicating that you want a Positional that only accepts that type as its elements. Now, as a parameter to a subroutine, that severely limits what you can specify, as [1,2,3] is not an array with a constraint on Int, it's an array that happens to be filled with Int values only.

    Now back to your example: what does (Array @r) mean? It means that you want a Positional that constrains on Array objects. In simple terms: you want an array that must consist of arrays as its elements.

    I don't think that is what you intended?

    Now, why does (Array $r) work? Because that indicates you want an object that is an Array as the parameter. This also limits what you want, because then it has to be an Array, and cannot be a List for instance.

    sub foo(Array $r) { ... }
    foo(@a);         # works
    foo( [1,2,3] );  # works
    foo( (1,2,3) );  # does *not* work
    

    Finally, I think you want to use the built-in dd instead of building your own report function.