I defined a multi sub
which has two signatures:
multi sub mie(Str $s, Int $i) { $s x $i }
multi sub mie(Int $s, Int $i) { ... }
say &mie.signature; # ;; Mu | is raw)
I want to get the signature of this multi sub
, but the above result is not what i expected.
As the document said, contains is a multi method which has 4 signatures:
multi method contains(Str:D: Cool:D $needle)
multi method contains(Str:D: Str:D $needle)
multi method contains(Str:D: Cool:D $needle, Int(Cool:D) $pos)
multi method contains(Str:D: Str:D $needle, Int:D $pos)
But when i try to get the signature of contains:
say "a string".^methods.pairs.values[8].value.signature;
It only output one signature:
(Str: | is raw)
In the REPL, when i call the contains
method without argument, it output the following error:
> "a string".contains()
Cannot resolve caller contains(Str: ); none of these signatures match:
(Str:D: Cool:D $needle, *%_)
(Str:D: Str:D $needle, *%_)
(Str:D: Cool:D $needle, Cool:D $pos, *%_)
(Str:D: Str:D $needle, Int:D $pos, *%_)
in block <unit> at <unknown file> line 1
That indicate that contains
method indeed has 4 signatures! I want to know is there any methods that can output all the signature of a method/multi method?
As a complement to Curt's answer:
proto foo (;; Mu | is raw) {*} # proto(;; Mu | is raw)
multi foo ($a) { } # multi($a)
multi foo (Int $a) { } # multi(Int $a)
multi foo ($a,$b) { } # multi($a, $b)
multi foo (Int $a,$b) { } # multi(Int $a, $b)
say 'proto', .signature for &foo; # displays 1 line
say 'multi', .signature for &foo.candidates; # displays 4 lines
I've shown the results of the say
s alongside their respective routines.
If you call foo ...
where foo
is a multiple dispatch routine (same with .foo
) then, at least semantically, you're actually calling a proto
declared for that name that then (normally) redispatches to the best fitting multi
with the same name.
(If you call methods on &foo
, rather than foo
, then you're calling them on the Routine
object for that proto
.)
A manually declared proto
provides complete control of the dispatch process. It can make a cup of tea and then use Common Lisp dispatch semantics and then fiddle with the result. Or whatever else it wants to do.
If one or more multi
s are declared without explicitly declaring a proto
then a default proto
is automatically generated. I've manually declared a proto
to ground the following:
The ;;
in the signature excludes parameters in the proto
sig from being relevant for "winning" the initial dispatch to it -- no matter what, the proto
"wins" the initial dispatch and gets all the arguments;
The Mu
parameter type constraint explicitly gives the broadest possible type to the |
parameter, which parameter binds to the entire list of arguments passed to it (in a Capture
), and the is raw
means the capture is received in its "raw" form (I currently don't understand what this trait does here; I had thought a Capture
is by definition a raw, unprocessed list of arguments).
The body then dispatches to the next same named routine (that's what the {*}
does).
Try "a string".^lookup('contains').candidates».signature
.^lookup('contains')
will find the Method
.candidates
will list the multi candidates
.signature
will give you the Signature
for each one.
Output:
((Str:D: Cool:D $needle, *%_) (Str:D: Str:D $needle, *%_) (Str:D: Cool:D $needle, Cool:D $pos, *%_) (Str:D: Str:D $needle, Int:D $pos, *%_))
You can use it for your multi sub
too:
say &mie.candidates».signature;
I made the P6Repl::Helper
module a while ago for this purpose.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With