(如何)raku 做 class 同义词?
(How) does raku do class synonyms?
我有
class Length is Measure export { ... }
我想要仅 class 名称不同的同义词,我试过这个:
class Distance is Length is export {}
class Breadth is Length is export {}
class Width is Length is export {}
class Height is Length is export {}
class Depth is Length is export {}
这种作品在那$distance ~~ Length,但我也想要$length ~~ Distance。
某种类型或强制转换是可取的 - 例如 $length.Distance ~~ 距离以阻止像 $width = $height + $depth 这样的操作(即你不能总是添加指向不同轴的长度)。
也许是某种 class 的 := 名称绑定,或者 shorthand 强制 NxN 的方式?
非常感谢收到的任何建议...
我可能需要再看几个用例才能百分百确定最佳方法是什么,但至少要确保所有长度
class A {
method ACCEPTS($other) { $other.isa: A }
}
class B is A { }
class C is A { }
class D is A { }
my $b = B.new;
my $c = C.new;
my $d = D.new;
say $b ~~ D; # True
say $d ~~ C; # True
say $c ~~ B; # True
因为 ACCEPTS
是在 A
上定义的,这将用于匹配 B
/C
/D
。默认情况下,接受使用 isa($?CLASS)
的智能匹配,这就是它 returns 错误的原因,但现在它会将其锁定为始终使用 A
。
另一种方法是将 class 设置为别名。这通常适用于缩短从模块导入的较长 class 的名称,但它也适用于此处:
class A { ... }
our \B = A; my $b = B.new;
our \C = A; my $c = C.new;
our \D = A; my $d = D.new;
say $b ~~ A & C & D; # True
say $b.WHAT; # A
say $b.WHAT; # A
say $b.WHAT; # A
您会注意到所有这些都声称是 A,因为它们确实是。我们所做的就是提供另一种访问 A 的方法。这意味着 B
不仅可以传递给 D
或 A
,而且 无法区分 来自他们,因为它对他们相同(直到它存储在内存中的位置)。
这还不是一个答案,但可能会变成一个答案。
以下标题对您有用吗?我并不一定意味着你要使用组合而不是继承(role
),或直接别名(constant
),或混入(but
),或动态类型约束(where
).在您提供反馈之前,下面的代码只是一种快速制作原型的方法。
role Measurement {}
role Height does Measurement {}
role Width does Measurement {}
constant Breadth = Width;
say Width; # (Width)
say Breadth; # (Width)
say ::<Breadth>:kv; # (Breadth (Width))
say Breadth ~~ Width; # True
say Width ~~ Breadth; # True
multi infix:<+>
(::L Measurement \l,
Measurement \r where * !~~ L)
{ fail }
say (42 but Width) + (99 but Breadth); # 141
say (42 but Width) + (99 but Height); # Failed...
我有
class Length is Measure export { ... }
我想要仅 class 名称不同的同义词,我试过这个:
class Distance is Length is export {}
class Breadth is Length is export {}
class Width is Length is export {}
class Height is Length is export {}
class Depth is Length is export {}
这种作品在那$distance ~~ Length,但我也想要$length ~~ Distance。
某种类型或强制转换是可取的 - 例如 $length.Distance ~~ 距离以阻止像 $width = $height + $depth 这样的操作(即你不能总是添加指向不同轴的长度)。
也许是某种 class 的 := 名称绑定,或者 shorthand 强制 NxN 的方式?
非常感谢收到的任何建议...
我可能需要再看几个用例才能百分百确定最佳方法是什么,但至少要确保所有长度
class A {
method ACCEPTS($other) { $other.isa: A }
}
class B is A { }
class C is A { }
class D is A { }
my $b = B.new;
my $c = C.new;
my $d = D.new;
say $b ~~ D; # True
say $d ~~ C; # True
say $c ~~ B; # True
因为 ACCEPTS
是在 A
上定义的,这将用于匹配 B
/C
/D
。默认情况下,接受使用 isa($?CLASS)
的智能匹配,这就是它 returns 错误的原因,但现在它会将其锁定为始终使用 A
。
另一种方法是将 class 设置为别名。这通常适用于缩短从模块导入的较长 class 的名称,但它也适用于此处:
class A { ... }
our \B = A; my $b = B.new;
our \C = A; my $c = C.new;
our \D = A; my $d = D.new;
say $b ~~ A & C & D; # True
say $b.WHAT; # A
say $b.WHAT; # A
say $b.WHAT; # A
您会注意到所有这些都声称是 A,因为它们确实是。我们所做的就是提供另一种访问 A 的方法。这意味着 B
不仅可以传递给 D
或 A
,而且 无法区分 来自他们,因为它对他们相同(直到它存储在内存中的位置)。
这还不是一个答案,但可能会变成一个答案。
以下标题对您有用吗?我并不一定意味着你要使用组合而不是继承(role
),或直接别名(constant
),或混入(but
),或动态类型约束(where
).在您提供反馈之前,下面的代码只是一种快速制作原型的方法。
role Measurement {}
role Height does Measurement {}
role Width does Measurement {}
constant Breadth = Width;
say Width; # (Width)
say Breadth; # (Width)
say ::<Breadth>:kv; # (Breadth (Width))
say Breadth ~~ Width; # True
say Width ~~ Breadth; # True
multi infix:<+>
(::L Measurement \l,
Measurement \r where * !~~ L)
{ fail }
say (42 but Width) + (99 but Breadth); # 141
say (42 but Width) + (99 but Height); # Failed...