Consider this program where I construct an Array in the argument list. Although there's a signature that accepts an Array, this calls the one that accepts a List:
foo( [ 1, 2, 3 ] );
multi foo ( Array @array ) { put "Called Array @ version" }
multi foo ( Array $array ) { put "Called Array \$ version" }
multi foo ( List $list ) { put "Called List version" }
multi foo ( Range $range ) { put "Called Range version" }
I get the output from an unexpected routine:
Called Array $ version
If I uncomment that other signature, that one is called:
Called List version
Why doesn't it call the ( Array @array )
version? How is the dispatcher making its decision (and where is it documented)?
Your test
foo
call has just an Array ([1,2,3]
) as its argument, not an Array ofArray
s (eg[[1,2,3],[4,5,6]]
).(The
@
in@array
indicates a value thatdoes Positional
, eg an array or a list.Array @array
indicates the same thing but with the additional constraint that each element of the array, list or whatever is anArray
.)Simplifying, it's picking the narrowest matching type:
(Diagram of subtype relationships of
Array
,List
andPositional
.)For lots of details see jnthn's authoritative answer to a related SO question.
I'm not sure about the doc. Multi-dispatch looks pretty minimal.
There seems to be a trade off between the design documents (more complete but more outdated) and the documentation (known to be incomplete, as docs.perl6.org acknowledges, but hopefully more up-to-date). The former explains multisub resolution in Synopsis 12. Excerpt:
I don’t know enough about Perl 6 to testify as to its accuracy, but it seems to be in agreement with raith’s answer, and covers additional ground as well.
I made a really dumb mistake, and that's why I wasn't seeing what I expected. You can't constrain a variable that starts with
@
. Any constraint applies to its elements. TheArray @array
denotes that I have a positional sort of thing in which each element is anArray
. This is the same thing that raiph said. The odd thing is that the grammar looks the same but it does different things. It's something I've tripped over before.Since it's doing something different, it's not going to work out even if the data structure matches:
I still get the version I wouldn't expect based on the constraint and the data structure:
I think this is just going to be one of Perl 6's warts that normal users will have to learn.