Perl 6多种方法永远不会匹配预期的签名

kaw*_*aii 10 oop method-signature perl6 multimethod

我有一个带有两个多方法的类(multi submit)。

我这样称呼我的多重:

$perspective.submit(:message($message.content));
Run Code Online (Sandbox Code Playgroud)

哪个运到我班上:

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>;
}
Run Code Online (Sandbox Code Playgroud)

但是我总是得到以下回应:

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, *%_)
Run Code Online (Sandbox Code Playgroud)

尽管我的命名参数(:message)是Str必需的,并且@models已声明默认值。

Jon*_*ton 12

多个调度工作分两个阶段:

  • 考虑位置参数的数量及其类型
  • 如果存在任何where子句,命名参数或子签名,请对签名进行测试绑定以查看其是否匹配

如果第二阶段由于任何原因无法绑定,则第二阶段将拒绝该候选人。这样的原因之一,我相信是造成此问题的原因,是默认值输入错误。例如,在:

multi m(:@x = "not-an-array") { }
m()
Run Code Online (Sandbox Code Playgroud)

我们收到一个错误:

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

但是将其更改为:

multi m(:@x = ["an-array"]) { }
m()
Run Code Online (Sandbox Code Playgroud)

工作正常。(请注意,尽管默认值使用=,但实际上是绑定,而不是赋值。)

在问题的情况下是这样的:

MODEL :@models = TOXICITY
Run Code Online (Sandbox Code Playgroud)

查看源代码的模块源,我看到:

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>
);
Run Code Online (Sandbox Code Playgroud)

因此,TOXICITY只是一个Int,但是期望的是类型化的MODEL值数组。

因此,如果您这样做:

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

它应该工作。


Bra*_*ert 8

我看到两个问题。

一种是您有两个方法相同,只是一个命名参数的名称不同。

命名参数可以具有别名:

#                       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>;
}
Run Code Online (Sandbox Code Playgroud)

请注意,这:$message真的很短:message($message)


现在,该问题实际上阻止了您的代码正常工作。

@modelsPositional,但是您在签名中为其分配了一个奇异值。

给它分配一个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>;
}
Run Code Online (Sandbox Code Playgroud)

  • 感谢您的回复 Brad,Jonathan 的解决方案实际上解决了我的核心问题,但我认为您做得很好,指出了可能会进一步咬我的代码,所以我也会考虑这些建议。:) (2认同)