【问题标题】:Object, roles and multiple dispatch对象、角色和多重分派
【发布时间】:2020-03-01 18:21:17
【问题描述】:

我正在尝试使用多个调度来重载和使用组合类中的方法。这是实现:

role A {
    has $!b;

    submethod BUILD( :$!b ) {}

    multi method bar () {
    return $!b;
    }
}

class B does A {

    submethod BUILD( :$!b ) {}

    multi method bar() {
    return " * " ~ callsame ~ " * ";
    }
}

my $a = A.new( b => 33);
say $a.bar();
my $b = B.new( b => 33 );
say $b.bar();

但是,这会失败,因为:

Calling callsame(Str) will never work with declared signature ()

(我真的不知道为什么 callame 使用Str 作为签名)。将method bar 更改为使用callwith

multi method bar() {
    return " * " ~ callwith() ~ " * ";
}

根本行不通:

Use of Nil in string context
  in method bar at multi.p6 line 18
 *  *

在角色/类中使用call* 有什么特殊的方法吗?

【问题讨论】:

    标签: roles raku multiple-dispatch


    【解决方案1】:

    第一个问题是语法问题。 listop 函数调用在它之后解析一个参数列表,从一个术语开始,所以:

    return " * " ~ callsame ~ " * ";
    

    这样的组:

    return " * " ~ callsame(~ " * ");
    

    所以你在“*”上调用~前缀运算符,这就是它抱怨的Str参数的来源。

    然而,归根结底,这里的问题是对角色组合和/或延迟的语义的误解。考虑一个非multi 的情况:

    role R { method m() { say 1; callsame() } }
    class B { method m() { say 2; callsame() } }
    class C is B does R { method m() { say 3; callsame(); } }
    C.m
    

    这个输出:

    3
    2
    

    请注意永远不会达到 1。这是因为角色组合是扁平化:就好像来自角色的代码被放入了类。当类已经有一个同名的方法时,它会被角色中的那个所采用。

    如果我们将multi 放在每个上面:

    role R { multi method m() { say 1; callsame() } }
    class B { multi method m() { say 2; callsame() } }
    class C is B does R { multi method m() { say 3; callsame(); } }
    C.m
    

    行为被保留:

    3
    2
    

    因为角色作曲家占multi method长名称 - 即占签名。既然他们是一样的,那么班上的人就赢了。如果两者都保留,我们最终会在最初的调用中导致一个模棱两可的调度错误!

    使用nextsamecallsamenextwithcallwith 进行延迟,所有这些都遍历了我们可以调度到的可能事物。

    在非multimethod的情况下,通过走MRO实现;由于来自角色的方法未组合,因此它不会出现在 MRO 中的任何类中(MRO 中仅出现类,因为角色在组合时被展平)。

    multimethod 的情况下,我们改为遍历将接受初始调度参数的候选集。同样,由于在组合时选择了类中相同的长名称方法来支持角色一,因此角色中的方法一开始根本不考虑调度:它不在候选者中proto 的列表,因此不会被推迟到。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-03
      • 2019-12-19
      • 2021-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多