我怎样才能发现 Perl 6 类型所扮演的所有角色



有了.does,我可以检查类型是否具有我已经知道的角色。我想获取角色列表。继承已经.^mro但我在元模型的东西中没有看到类似的东西。

除此之外,给定一个"类型",我如何判断它是被定义为类还是角色?

.^roles
say Rat.^roles; # ((Rational[Int,Int]) (Real) (Numeric))

默认情况下,它包括每个角色,包括其他角色引入的角色。仅获取第一级使用:!transitive

Rat.^roles(:!transitive); # ((Rational[Int,Int]))

第一个问题已经有一个很好的答案。关于第二个,每个元对象都有一个archetypes方法,该方法又携带由该元类型表示的类型范围的一系列属性。这是因为 Perl 6 对新的元类型开放(可能更容易被认为是"类型类型");今天使用最广泛的例子可能是OO::Monitors.原型更侧重于可以对该类型执行的操作。例如:

> role R { }; say "C: {.composable} I: {.inheritable}" given R.HOW.archetypes; 
C: 1 I: 0
> class C { }; say "C: {.composable} I: {.inheritable}" given C.HOW.archetypes; 
C: 0 I: 1

可以自检可用属性集:

> Int.HOW.archetypes.^methods(:local)
(nominal nominalizable inheritable inheritalizable composable 
composalizable generic parametric coercive definite augmentable)

例如,"名义"的意思是"这可以作为名义类型","可增强"的意思是"是否允许增加这种类型"。像"可继承"这样的东西意味着"我可以继承这样的类型吗"——也就是说,把它变成一个我可以继承的类型,即使我不能从这个类型继承。role不可继承,但它是可继承的,对其的继承操作将产生角色的双关语。这就是在编写类似class C is SomeRole { }的东西时正在发生的事情,这意味着 Perl 6 不仅对新类型开放,而且这些新类型可以描述它们想要如何工作,如果有的话,继承和组合。

可与does组合可能是角色的主要定义属性,因此在询问"这是一个角色吗"时,composable属性可能是最好的属性。也可以查看元对象的类型,如另一个答案中所建议的那样,但是表示角色涉及多个元对象(短名称角色组,带有参数的该组的柯里化,以及单个角色,以及支持组合过程的内部具体化形式)。

> say (role RRR[::T] { }).HOW.^name
Perl6::Metamodel::ParametricRoleHOW
> say RRR.HOW.^name
Perl6::Metamodel::ParametricRoleGroupHOW
> say RRR[Int].HOW.^name
Perl6::Metamodel::CurriedRoleHOW

因此,简单地检查事物是否可组合更为健壮。

> say (role RRR[::T] { }).HOW.archetypes.composable
1
> say RRR.HOW.archetypes.composable
1
> say RRR[Int].HOW.archetypes.composable
1

除此之外,给定一个"类型",我如何判断它是定义为类还是角色?

类是元类的类型为Metamodel::ClassHOW

sub type-classify(Mu t) {
given t.HOW {
return 'class' when Metamodel::ClassHOW;
return 'role'  when Metamodel::ParametricRoleGroupHOW;
}
return 'other';
}
say type-classify(Int);         # class
say type-classify(Rational);    # role
say type-classify(Bool);        # other

关于你的第二个问题,

给定一个"类型",我如何判断它是定义为类还是角色?

我还没有找到直接的方法。类和角色的层次结构中都有 Mu,因此无法区分它们。但是,只有类才能被(奇怪的名字)MetaModel::ClassHOW识别。所以我们可以破解这样的东西:

role Ur { }
role F does Ur { }
class G does F { }
for Ur, F, G -> $class-or-role {
CATCH {
default {
say "not classy";
}
}
$class-or-role.say;
$class-or-role.^mro.say;
}

这将打印:

(Ur)
not classy
(F)
not classy
(G)
((G) (Any) (Mu))

,因为调用角色^mro将引发异常。这可以变成一个函数,用于打印出哪个是角色,哪个不是。

最新更新