如何为角色组编写模块?

Kai*_*epi 8 polymorphism types module raku

角色的一个特性是角色组,它允许你声明多个同名角色接受不同的参数,类似于多例程:

role Foo[Int:D] {
    method is-int(::?CLASS:_: --> True)  { }
    method is-str(::?CLASS:_: --> False) { }
}
role Foo[Str:D] {
    method is-int(::?CLASS:_: --> False) { }
    method is-str(::?CLASS:_: --> True)  { }
}
Run Code Online (Sandbox Code Playgroud)

通常,对于一种类型,您有一个模块。问题是unit一个模块中只能有一个作用域声明,因此不能将它与角色组一起使用。如何为角色组编写模块?

Kai*_*epi 9

您可以unit在其中包含没有作用域声明的模块并从中导出符号,但是如何导出角色组有点问题。您不能is export为此使用trait,因为这会导出错误的类型。当您在声明后引用角色时,您指的是角色组,而不是其中的单个角色,但是is export在单个角色上使用将导出这些单个角色,而不是角色的组。单个角色与角色组有非常不同的 HOW,并且不会像您通常期望的角色那样行事!

幸运的是,有一种方法可以使用EXPORT包来做到这一点。Foo在这个包中声明角色组会给它一个EXPORT::DEFAULT::Foo你可能不想要的名称,所以你需要MY在单元的范围内声明它并为它声明一个常量EXPORT::DEFAULT

use v6.d;

my role Foo[Int:D] {
    method is-int(::?CLASS:_: --> True)  { }
    method is-str(::?CLASS:_: --> False) { }
}
my role Foo[Str:D] {
    method is-int(::?CLASS:_: --> False) { }
    method is-str(::?CLASS:_: --> True)  { }
}

my package EXPORT::DEFAULT {
    constant Foo = ::Foo;
}
Run Code Online (Sandbox Code Playgroud)

现在Foo可以导入使用OK了:

use Foo;

say ::<Foo>:exists;       # OUTPUT: True
say try Foo[1].is-int;    # OUTPUT: True
say try Foo['ok'].is-str; # OUTPUT: True
Run Code Online (Sandbox Code Playgroud)

注意:您不能::在常量名称中使用,因此要在命名空间中导出角色组,您需要将其包装在另一个包中:

my role Foo::Bar[Int:D] { }
my role Foo::Bar[Str:D] { }

my package EXPORT::DEFAULT {
    package Foo {
        constant Bar = Foo::Bar;
    }
}
Run Code Online (Sandbox Code Playgroud)