Raku 中的参数化类型,如何使用运行时值作为参数

jjm*_*elo 10 roles raku

我想为 Raku创建一些参数化类型;基本上,我想创建一些不同的类,它们的主要区别在于其属性之一的值范围;例如,类代表建筑物的类型,我想为 3 层或任何其他楼层数的建筑物设置不同的类。所以这是我能想到的最好的:

subset Two-Tops of UInt where * <=2;
subset Three-Tops of UInt where * <=3;

role Zipi[ ::Capper ] {
    has Capper $.floor;
}
    
class Capped-at-three does Zipi[Three-Tops] {}


my $capped = Capped-at-three.new( floor => 2 );
say $capped.raku;
Run Code Online (Sandbox Code Playgroud)

一旦您需要处理许多不同数量的楼层,这显然是不切实际的(不是在格拉纳达,我认为他们最多只有 10 层,但是……)。这里的问题基本上是您需要在编译时获得子集的信息,因此除非您使用(仍处于实验阶段),否则您无法使用任何类型的变量。那么你能想出一种实用的方法来为参数的任何值定义这种柯里化角色吗?

use*_*601 8

实际上,与我之前所说的不同,您可以毫无问题地在 where 子句中使用条件,您只需要将它们括在大括号中:

role Zipi[$condition] {
    has $.floor is rw where {$_ ~~ $condition}
    method foo($x) { $!floor = $x }
}

class A does Zipi[2 < * < 5] {
    method bar($x) { $.floor = $x }
}

#my $a = A.new( floor => 10); # error
my $a = A.new( floor => 4); # OK

#$a.foo(10); # error
$a.foo(3); # OK

#$a.bar(0); # error
$a.bar(4); # OK

#$a.floor = 9; # error
$a.floor = 3; # OK
Run Code Online (Sandbox Code Playgroud)

这应该涵盖所有分配类型


rai*_*iph 5

我的 MOP 印章非常有限,以下内容看起来很丑陋,但它有效,并且可能是朝着正确方向迈出的一步。

我所做的:

  • subset通过 MOP动态构建了一个 10,000秒的数组。

  • 时间通过BEGIN.

  • 使用数组中的适当元素来参数化角色。

my @max-floors-checkers; 
BEGIN {
  @max-floors-checkers = do for ^10_000 -> \floors {
    Metamodel::SubsetHOW.new_type: 
      refinee => UInt,
      refinement => { $^floors <= floors }
    }
}

role BuildingCategory[ ::MaxFloorsCheck ] { has MaxFloorsCheck $.floors }
    
class Capped-at-three does BuildingCategory[ @max-floors-checkers[3] ] {}

my $capped3 = Capped-at-three.new( floors => 2 );
say $capped3.raku;                                # Capped-at-three.new(floors => 2

my $capped4 = Capped-at-three.new( floors => 4 ); # Type check failed 
Run Code Online (Sandbox Code Playgroud)

  • 尽管我为手头的特定任务想出了一种更简单的方法……这真是令人难以置信。从来没有想过要创建这么多这样的子集。 (2认同)