Как получить все подписи нескольких суб или встроенных модулей?

Я определил multi sub который имеет две подписи:

multi sub mie(Str $s, Int $i) { $s x $i }
multi sub mie(Int $s, Int $i) { ... }
say &mie.signature; # ;; Mu | is raw)

Я хочу получить подпись этого multi sub, но результат выше не тот, который я ожидал.

Как сказано в документе, содержит многоуровневый метод, который имеет 4 подписи:

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)

Но когда я пытаюсь получить подпись содержит:

say "a string".^methods.pairs.values[8].value.signature; 

Он выводит только одну подпись:

(Str: | is raw)

В REPL, когда я вызываю метод contains без аргумента, он выдает следующую ошибку:

> "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

Это указывает, что contains метод действительно имеет 4 подписи! Я хочу знать, есть ли какие-либо методы, которые могут выводить всю подпись метода /multi?

Ответ 1

Попробуйте "a string".^lookup('contains').candidates".signature

.^lookup('contains') найдет Method

.candidates перечислит несколько кандидатов

.signature даст вам Signature для каждого.

Выход: ((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, *%_))

Вы можете использовать его для своего multi sub:

say &mie.candidates".signature;

Ответ 2

В качестве дополнения к ответу Курта:

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

Я показал результаты say наряду с их соответствующими рутин.

Если вы звоните foo... где foo является множественная диспетчеризация рутина ( то же самое с .foo), то, по крайней мере, семантически, вы на самом деле захода в proto объявлен для этого имени, которое затем (обычно) переотправляет к лучшему примерка multi с то же имя. Если вы вызываете методы on &foo вы вызываете их на proto для foo.

Вручную объявлено proto обеспечивает полный контроль процесса диспетчеризации. Он может сделать чашку чая, а затем использовать семантику Common Lisp dispatch, а затем поиграть с результатом. Или что еще он хочет сделать.

Если один или несколько multi объявляются без явного объявить proto то по умолчанию proto автоматически генерируется. Я вручную объявил proto который показывает, что это по умолчанию:

  • ;; исключает параметры в proto из-за того, что они относятся к первоначальной отправке;

  • Mu явно дает общий тип списка аргументов, передаваемых самым широким возможным типом (потому что, если вы не укажете, то это более узкий Any для параметров);

  • По умолчанию proto принимает все аргументы (то, что | в круглых скобках делает);

  • Аргументы принимаются в необработанном виде (is raw);

  • Тело отправляется к следующей же именованной процедуре (что делает {*}).

Ответ 3

Для этого я сделал модуль P6Repl::Helper.