【问题标题】:Perl 6 multi methods never match expected signaturePerl 6 多方法从不匹配预期的签名
【发布时间】:2019-11-07 12:16:14
【问题描述】:

我有一个包含两个多方法的类 (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 声明了默认值。

【问题讨论】:

标签: oop raku method-signature multimethod


【解决方案1】:

我看到了两个问题。

一个是你有两种方法,除了一个命名参数的名称之外,它们是相同的。

命名参数可以有别名:

#                       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 是一个位置,但您在签名中为其分配了一个奇异值。

为它分配一个位置,它就可以工作了:
(在这种情况下,它必须是 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>;
}

【讨论】:

  • 感谢您的回复布拉德,乔纳森的解决方案实际上解决了我的核心问题,但我认为您做得很好,指出代码可能会进一步咬我,所以我会接受这些建议也考虑在内。 :)
  • @raiph 我在测试时尝试了一小部分问题。
  • 嗨布拉德。但是... 命名参数别名 你是说你提到的命名参数别名方面现在应该被理解为纯粹是关于代码读者可能会感到困惑吗?或者您是否看到测试中出现问题的实例?或者即使您在测试中没有看到问题,也能预见问题? Array[Model] 您是否同意 OP 的关键问题是 Bar @baz 参数或类似参数必须绑定到 Foo[Bar] 参数,而 FooPositional 绑定?也许我的问题的答案对某些人来说是显而易见的,但对我来说不是。 TIA 回复。
【解决方案2】:

多分派分两个阶段进行:

  • 考虑位置参数的数量及其类型
  • 如果有任何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)) {

它应该可以工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-12
    • 2018-01-15
    • 2019-09-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多