Perl 6 multi методы никогда не соответствуют ожидаемой подписи - PullRequest
10 голосов
/ 25 июня 2019

У меня есть класс с двумя multi методами (multi submit).

Я называю мой мульти такой:

$perspective.submit(:message($message.content));

Который отправляется в мой класс:

my $perspective-api = API::Perspective.new(:api-key(%*ENV<PERSPECTIVE_API_KEY>));

proto method submit (|) {*}

multi method submit(Str :$message!, MODEL :@models = TOXICITY) {
    my $score = $perspective-api.analyze(:@models, :comment($message));
    say @models Z=> $score<attributeScores>{@models}.map: *<summaryScore><value>;

multi method submit(Str :$name!, MODEL :@models = TOXICITY) {
    my $score = $perspective-api.analyze(:@models, :comment($name));
    say @models Z=> $score<attributeScores>{@models}.map: *<summaryScore><value>;
}

Однако я всегда получаю следующий ответ:

Died because of the exception:
    Cannot resolve caller AUTOGEN(Rose::ContentAnalysis::Perspective:D: :message(Str)); none of these signatures match:
        (Rose::ContentAnalysis::Perspective: Str :$message!, MODEL :@models = MODEL::TOXICITY, *%_)
        (Rose::ContentAnalysis::Perspective: Str :$name!, MODEL :@models = MODEL::TOXICITY, *%_)

Несмотря на то, что мой именованный аргумент (:message) является Str, как требуется, и @models имеет объявленное по умолчанию.

Ответы [ 2 ]

12 голосов
/ 25 июня 2019

Многократная отправка работает в два этапа:

  • С учетом количества позиционных параметров и их типов
  • Если есть какие-либо условия where, именованные параметры или субподписи, выполните тестовую привязку подписи, чтобы проверить, соответствует ли она

Второй этап отклонит кандидата, если он не сможет связываться по какой-либо причине. Одна из таких причин, и я полагаю, что причина проблемы заключается в том, что значение по умолчанию неправильно введено. Например, в:

multi m(:@x = "not-an-array") { }
m()

Получаем ошибку:

Cannot resolve caller m(...); none of these signatures match:
    (:@x = "not-an-array")
  in block <unit> at -e line 1

Но изменив его на:

multi m(:@x = ["an-array"]) { }
m()

Работает нормально. (Обратите внимание, что хотя значение по умолчанию использует =, на самом деле это привязка, а не присвоение.)

В случае в вопросе есть это:

MODEL :@models = TOXICITY

Глядя на источник модуля, из которого взят код, я вижу:

enum MODEL is export (
        <TOXICITY SEVERE_TOXICITY TOXICITY_FAST IDENTITY_ATTACK
        INSULT PROFANITY SEXUALLY_EXPLICIT THREAT FLIRTATION
        ATTACK_ON_AUTHOR ATTACK_ON_COMMENTER INCOHERENT INFLAMMATORY
        LIKELY_TO_REJECT OBSCENE SPAM UNSUBSTANTIAL>
);

Таким образом, TOXICITY - это просто Int, но ожидается, что это типизированный массив значений MODEL.

Таким образом, если вы сделаете это:

multi method submit(Str :$message!, MODEL :@models = Array[MODEL](TOXICITY)) {

Должно работать.

8 голосов
/ 25 июня 2019

Я вижу две проблемы.

Во-первых, у вас есть два идентичных метода, кроме имени одного именованного параметра.

Именованные параметры могут иметь псевдонимы:

#                       V--------------V
multi method submit(Str :name(:$message)!, MODEL :@models = TOXICITY) {
    my $score = $perspective-api.analyze(:@models, :comment($message));
    say @models Z=> $score<attributeScores>{@models}.map: *<summaryScore><value>;
}

Обратите внимание, что :$message действительно коротко для :message($message)


Теперь о проблеме, которая фактически препятствует работе вашего кода.

@models - это Positional , но вы присваиваете ему единственное значение в подписи.

Присвойте ему Positional , и оно работает:
(В этом случае это должно бытьтипа Array[MODEL] из-за объявления типа MODEL.)

#                                                           V---------------------V
multi method submit(Str :name(:$message)!, MODEL :@models = Array[MODEL](TOXICITY,)) {
    my $score = $perspective-api.analyze(:@models, :comment($message));
    say @models Z=> $score<attributeScores>{@models}.map: *<summaryScore><value>;
}
...