gpt4 book ai didi

raku - 别名为常量时无法解析签名

转载 作者:行者123 更新时间:2023-12-03 13:47:33 26 4
gpt4 key购买 nike

作为 this question about using different APIs in a single program 的后续行动, Liz Mattijsen suggested to use constants .现在这里有一个不同的用例:让我们尝试创建一个 multi 按 API 版本区分,如下所示:

class WithApi:ver<0.0.1>:auth<github:JJ>:api<1>  {}
my constant two = my class WithApi:ver<0.0.1>:auth<github:JJ>:api<2> {}

multi sub get-api( WithApi $foo where .^api() == 1 ) {
return "That's version 1";
}

multi sub get-api( WithApi $foo where .^api() == 2 ) {
return "That's version deuce";
}

say get-api(WithApi.new);
say two.new.^api;
say get-api(two.new);

我们在第二个版本中使用了一个常量,因为两者不能一起在一个符号空间中。但这会产生这个错误:
That's version 1
2
Cannot resolve caller get-api(WithApi.new); none of these signatures match:
(WithApi $foo where { ... })
(WithApi $foo where { ... })
in block <unit> at ./version-signature.p6 line 18

所以 say two.new.^api;返回正确的api版本,调用者是 get-api(WithApi.new) , 所以 $foo具有正确的类型和正确的 API 版本,但没有调用 multi?我在这里缺少什么吗?

最佳答案

TL;DR JJ's answer是运行时 where子句在关注的论点上调用一对方法。其他人的答案都做同样的工作,但使用提供更好检查和更好性能的编译时构造。这个答案将我的观点与 Liz 和 Brad 的观点融为一体。

JJ 答案的主要优点和缺点

在 JJ 的回答中,所有逻辑都包含在 where 中。条款。相对于其他所有人的答案,这是它相对于解决方案的唯一优势;它根本没有添加任何 LoC。

JJ 的解决方案有两个明显的弱点:

  • where 的检查和调度开销参数上的子句是在运行时产生的 1。即使谓词不是,这也是代价高昂的。在 JJ 的解决方案中,谓词是昂贵的,使事情变得更糟。总而言之,使用多重分派(dispatch)时的最坏情况下的开销是所有 where 的总和。 multi 中使用的所有子句s。
  • 在代码 where .^api() == 1 && .^name eq "WithApi" , 每个 multi 的 43 个字符中有 42 个重复变体。相比之下,非 where子句类型约束要短得多,不会掩盖差异。当然,JJ 可以声明 subset s 具有类似的效果,但这会消除他们解决方案的唯一优势,而不会修复其最重要的弱点。

  • 附加编译时元数据;在多次调度中使用它

    在特别讨论 JJ 的问题之前,这里有一些通用技术的变体:
    role Fruit {}                             # Declare metadata `Fruit`

    my $vegetable-A = 'cabbage';
    my $vegetable-B = 'tomato' does Fruit; # Attach metadata to a value

    multi pick (Fruit $produce) { $produce } # Dispatch based on metadata

    say pick $vegetable-B; # tomato

    再次相同,但参数化:
    enum Field < Math English > ;

    role Teacher[Field] {} # Declare parameterizable metadata `Teacher`

    my $Ms-England = 'Ms England';
    my $Mr-Matthews = 'Mr Matthews';

    $Ms-England does Teacher[Math];
    $Mr-Matthews does Teacher[English];

    multi field (Teacher[Math]) { Math }
    multi field (Teacher[English]) { English }

    say field $Mr-Matthews; # English

    我用了 role作为元数据,但这是偶然的。关键是要有可以在编译时附加的元数据,并且它有一个类型名称,以便可以在编译时建立调度解决方案候选者。

    JJ 运行时答案的编译时元数据版本

    解决方案是声明元数据并将其附加到 JJ 的类中。

    布拉德解决方案的变体:
    class WithApi1 {}
    class WithApi2 {}

    constant one = anon class WithApi:ver<0.0.1>:auth<github:JJ>:api<1> is WithApi1 {}

    constant two = anon class WithApi:ver<0.0.1>:auth<github:JJ>:api<2> is WithApi2 {}

    constant three = anon class WithApi:ver<0.0.2>:api<1> is WithApi1 {}

    multi sub get-api( WithApi1 $foo ) { "That's api 1" }

    multi sub get-api( WithApi2 $foo ) { "That's api deuce" }

    say get-api(one.new); # That's api 1
    say get-api(two.new); # That's api deuce
    say get-api(three.new); # That's api 1

    另一种方法是编写一个可参数化的元数据项:
    role Api[Version $] {}

    constant one = anon class WithApi:ver<0.0.1>:auth<github:JJ>:api<1> does Api[v1] {}

    constant two = anon class WithApi:ver<0.0.1>:auth<github:JJ>:api<2> does Api[v2] {}

    constant three = anon class WithApi:ver<0.0.2>:api<v1> does Api[v1] {}

    multi sub get-api( Api[v1] $foo ) { "That's api 1" }

    multi sub get-api( Api[v2] $foo ) { "That's api deuce" }

    say get-api(one.new); # That's api 1
    say get-api(two.new); # That's api deuce
    say get-api(three.new); # That's api 1

    版本匹配范围

    在下面的评论中,JJ 写道:

    If you use where clauses you can have multis that dispatch on versions up to a number (so no need to create one for every version)


    role此答案中涵盖的解决方案还可以通过添加另一个角色来分派(dispatch)版本范围:
    role Api[Range $ where { .min & .max ~~ Version }] {}

    ...

    multi sub get-api( Api[v1..v3] $foo ) { "That's api 1 thru 3" }

    #multi sub get-api( Api[v2] $foo ) { "That's api deuce" }

    这显示 That's api 1 thru 3所有三个电话。如果第二个 multi 未注释,则 v2 优先。来电。

    请注意 get-api尽管角色签名包含 where,但仍会检查例程调度并在编译时解析候选者条款。这是因为运行角色的运行时 where子句在 get-api 的编译期间常规;当 get-api例程称为角色的 where条款不再相关。

    脚注

    1 在 Multiple Constraints ,拉里写道:

    For 6.0.0 ... any structure type information inferable from the where clause will be ignored [at compile-time]



    但对于 future ,他猜想:
    my enum Day ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];

    Int $n where 1 <= * <= 5 # Int plus dynamic where
    Day $n where 1 <= * <= 5 # 1..5

    The first where is considered dynamic not because of the nature of the comparisons but because Int is not finitely enumerable. [The second constraint] ... can calculate the set membership at compile time because it is based on the Day enum, and hence [the constraint, including the where clause] is considered static despite the use of a where.

    关于raku - 别名为常量时无法解析签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61057164/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com