(如何)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 不仅可以传递给 DA,而且 无法区分 来自他们,因为它对他们相同(直到它存储在内存中的位置)。

这还不是一个答案,但可能会变成一个答案。

以下标题对您有用吗?我并不一定意味着你要使用组合而不是继承(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...