jjm*_*elo 3 roles multiple-dispatch raku
我正在尝试使用多个分派来重载和使用组合类中的方法。这是实现:
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();
Run Code Online (Sandbox Code Playgroud)
但是,此操作失败:
Calling callsame(Str) will never work with declared signature ()
Run Code Online (Sandbox Code Playgroud)
(我真的不知道为什么callame Str用作签名)。更改method bar为使用callwith:
multi method bar() {
return " * " ~ callwith() ~ " * ";
}
Run Code Online (Sandbox Code Playgroud)
根本行不通:
Use of Nil in string context
in method bar at multi.p6 line 18
* *
Run Code Online (Sandbox Code Playgroud)
call*在角色/类中是否有任何特殊的处理方式?
第一个问题是语法问题。一个listop函数调用从一个术语开始解析其后的参数列表,因此:
return " * " ~ callsame ~ " * ";
Run Code Online (Sandbox Code Playgroud)
像这样的团体:
return " * " ~ callsame(~ " * ");
Run Code Online (Sandbox Code Playgroud)
因此,您要~在“ *”上调用前缀运算符,这是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
Run Code Online (Sandbox Code Playgroud)
输出:
3
2
Run Code Online (Sandbox Code Playgroud)
注意如何永远不会达到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
Run Code Online (Sandbox Code Playgroud)
该行为被保留:
3
2
Run Code Online (Sandbox Code Playgroud)
因为角色编写者考虑了-的长名称,multi method即考虑了签名。由于它们是相同的,因此该类中的一个获胜。如果要保留两者,我们将以初始调用结束,从而导致模棱两可的调度错误!
延迟使用nextsame,,callsame和nextwith,然后callwith遍历我们本来可以调度到的所有可能东西。
在非情况下multi method,这是通过步行MRO来实现的;因为没有组合角色中的方法,所以它不会出现在MRO中的任何类中(因为角色在组合时变平了,所以只有类出现在MRO中)。
在a的情况下multi method,我们改为遍历将接受初始调度的参数的候选集。再次,由于在类中选择了相同名称的方法来支持编写时的角色,因此首先不考虑该角色中的角色:它不在候选对象中的列表proto,因此不会被延迟。
| 归档时间: |
|
| 查看次数: |
54 次 |
| 最近记录: |