Как получить все подписи нескольких суб или встроенных модулей?
Я определил 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
.