我怎样才能发现一个 Perl 6 类型的所有角色?
How can I discover all the roles a Perl 6 type does?
使用 .does
我可以检查一个类型是否具有我已知的角色。我想获得角色列表。继承有 .^mro
,但我在元模型中没有看到类似的角色。
除此之外,给定一个 "type",我如何判断它是被定义为 class 还是一个角色?
.^roles
say Rat.^roles; # ((Rational[Int,Int]) (Real) (Numeric))
默认情况下它包括每个角色,包括由其他角色引入的角色。要仅获得第一级,请使用 :!transitive
Rat.^roles(:!transitive); # ((Rational[Int,Int]))
关于你的第二个问题,
given a "type", how can I tell if it was defined as a class or a role?
我还没有找到直接的方法。 类 和角色都有 Mu in their hierarchy, so that will not distinguish them. However, only classes get to be recognized by (the curiously named) 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
会引发异常。这可以变成一个函数来打印出哪个是角色,哪个不是。
Along with that, given a "type", how can I tell if it was defined as a class or a role?
A class 是一种类型,其元 class 的类型为 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
第一个问题已经有了很好的答案。关于第二个,每个元对象都有一个 archetypes
方法,该方法依次携带该元类型所表示的类型的一系列属性。这是因为 Perl 6 对新的元类型开放(这可能更容易被认为是 "types of type");今天使用最广泛的例子可能是 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)
例如,"nominal"表示"can this serve as a nominal type","augmentable"表示"is it allowed to augment this kind of type"。 "inheritalizable" 之类的意思是 "can I inheritalize such a type" ——也就是说,把它变成我 可以 继承的类型,即使我不能从这种类型继承。一个role
不是可继承的,而是可继承的,对其进行inheritalize操作会产生作用的双关。这就是写 class C is SomeRole { }
之类的东西时发生的事情,这意味着 Perl 6 不仅对新类型开放,而且这些新类型可以描述它们想要如何工作,如果有的话, 具有继承和组合。
可与 does
组合可能是角色的主要定义 属性,因此 composable
属性 可能是询问 "is this a role".也可以查看元对象的类型,如另一个答案中所建议的,但是表示角色涉及多个元对象(简称角色组,该组的参数化,以及个人角色,加上支持组合过程的内部具体化形式)。
> 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
使用 .does
我可以检查一个类型是否具有我已知的角色。我想获得角色列表。继承有 .^mro
,但我在元模型中没有看到类似的角色。
除此之外,给定一个 "type",我如何判断它是被定义为 class 还是一个角色?
.^roles
say Rat.^roles; # ((Rational[Int,Int]) (Real) (Numeric))
默认情况下它包括每个角色,包括由其他角色引入的角色。要仅获得第一级,请使用 :!transitive
Rat.^roles(:!transitive); # ((Rational[Int,Int]))
关于你的第二个问题,
given a "type", how can I tell if it was defined as a class or a role?
我还没有找到直接的方法。 类 和角色都有 Mu in their hierarchy, so that will not distinguish them. However, only classes get to be recognized by (the curiously named) 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
会引发异常。这可以变成一个函数来打印出哪个是角色,哪个不是。
Along with that, given a "type", how can I tell if it was defined as a class or a role?
A class 是一种类型,其元 class 的类型为 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
第一个问题已经有了很好的答案。关于第二个,每个元对象都有一个 archetypes
方法,该方法依次携带该元类型所表示的类型的一系列属性。这是因为 Perl 6 对新的元类型开放(这可能更容易被认为是 "types of type");今天使用最广泛的例子可能是 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)
例如,"nominal"表示"can this serve as a nominal type","augmentable"表示"is it allowed to augment this kind of type"。 "inheritalizable" 之类的意思是 "can I inheritalize such a type" ——也就是说,把它变成我 可以 继承的类型,即使我不能从这种类型继承。一个role
不是可继承的,而是可继承的,对其进行inheritalize操作会产生作用的双关。这就是写 class C is SomeRole { }
之类的东西时发生的事情,这意味着 Perl 6 不仅对新类型开放,而且这些新类型可以描述它们想要如何工作,如果有的话, 具有继承和组合。
可与 does
组合可能是角色的主要定义 属性,因此 composable
属性 可能是询问 "is this a role".也可以查看元对象的类型,如另一个答案中所建议的,但是表示角色涉及多个元对象(简称角色组,该组的参数化,以及个人角色,加上支持组合过程的内部具体化形式)。
> 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