Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get all the signatures of multi sub or build-ins?

Tags:

raku

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?

like image 793
chenyf Avatar asked Sep 26 '18 10:09

chenyf


3 Answers

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 says 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 multis 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).

like image 160
raiph Avatar answered Nov 08 '22 16:11

raiph


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;

like image 11
Curt Tilmes Avatar answered Nov 08 '22 17:11

Curt Tilmes


I made the P6Repl::Helper module a while ago for this purpose.

like image 2
cowbaymoo Avatar answered Nov 08 '22 17:11

cowbaymoo