Как получить все подписи multi sub или build-ins? - PullRequest
0 голосов
/ 26 сентября 2018

Я определил 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 метода?

Ответы [ 3 ]

0 голосов
/ 26 сентября 2018

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

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 s вместе с соответствующими им подпрограммами.

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

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

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

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

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

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

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

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

0 голосов
/ 09 октября 2018

Я сделал модуль P6Repl::Helper некоторое время назад для этой цели.

0 голосов
/ 26 сентября 2018

Попробуйте "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;

...