gpt4 book ai didi

roles - 对象、角色和多重分派(dispatch)

转载 作者:行者123 更新时间:2023-12-01 08:28:46 25 4
gpt4 key购买 nike

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

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 作为签名)。更改方法条 以使用callwith :

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

根本行不通:

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

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

最佳答案

第一个问题是语法问题。一个 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

因为角色 Composer 考虑了multi 方法长名称 - 即,考虑了签名。由于它们完全相同,因此类(class)中的那个获胜。如果它同时保留两者,我们将以初始调用结束,导致不明确的调度错误!

Deferral nextsamecallsamenextwithcallwith 都迭代了我们可能拥有的东西发送到。

在非multi method 的情况下,这是通过遍历 MRO 实现的;由于角色中的方法未组合,因此它不会出现在 MRO 中的任何类中(只有类出现在 MRO 中,因为角色在组合时被扁平化)。

multi method 的情况下,我们取而代之的是遍历那些会接受初始调度参数的候选集。同样,由于在组合时选择了类中具有相同长名称的方法以支持角色,因此首先根本不考虑来自角色的方法:它不在候选中proto 的列表,因此不会被推迟到。

关于roles - 对象、角色和多重分派(dispatch),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58710288/

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