Oop 我如何发现Perl6类型的所有角色?

Oop 我如何发现Perl6类型的所有角色?,oop,roles,raku,metamodel,Oop,Roles,Raku,Metamodel,使用.does我可以检查类型是否具有我已知的角色。我想得到角色列表。继承有^mro,但我在元模型中没有看到类似的角色 此外,给定一个“类型”,我如何判断它是定义为类还是角色?^roles 说老鼠。^roles;#((有理[Int,Int])(实)(数字)) 默认情况下,它包括每个角色,包括由其他角色引入的角色。要仅获取第一级,请使用:!可传递的 Rat.^roles(:!transitive);#((有理[Int,Int])) 关于第二个问题 给定一个“类型”,我如何判断它是定义为类还是角色

使用
.does
我可以检查类型是否具有我已知的角色。我想得到角色列表。继承有
^mro
,但我在元模型中没有看到类似的角色

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

^roles
说老鼠。^roles;#((有理[Int,Int])(实)(数字))
默认情况下,它包括每个角色,包括由其他角色引入的角色。要仅获取第一级,请使用
:!可传递的

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

关于第二个问题

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

我还没有找到一个直接的方法。类和角色在其层次结构中都具有相同的属性,因此不会区分它们。然而,只有类才能被(奇怪的命名)识别。所以我们可以破解这样的东西:

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
将引发异常。这可以转化为一个函数,用于打印出哪个角色是角色,哪个不是角色

此外,给定一个“类型”,我如何判断它是定义为类还是角色

类是一种类型,其元类的类型为
元模型::ClassHOW

子类型分类(Mu\t){
给定t.HOW{
当元模型::ClassHOW时返回“class”;
当元模型::ParameterRoleGroupHow时返回“角色”;
}
返回“其他”;
}
说类型分类(Int);#班
说类型分类(有理);#角色
说类型分类(Bool);#其他

第一个问题已经有了很好的答案。关于第二个,每个元对象都有一个
原型
方法,该方法依次携带由该元类型表示的类型的一系列属性。这是因为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)
例如,“nominal”表示“this可以作为一个nominal类型使用”,而“augmentable”则表示“它可以扩展这种类型”。像“可继承”这样的词意味着“我可以继承这样一个类型吗”——也就是说,将它转换成一个我可以从中继承的类型,即使我不能从这个类型继承。
角色
是不可继承的,但它是可继承的,对它的继承操作将产生角色的双关语。这就是在编写类似
类C是SomeRole{}
的代码时发生的情况,这意味着Perl 6不仅对新类型的类型开放,而且这些新类型可以描述它们希望如何使用继承和组合来工作

does
组合可能是角色的主要定义属性,因此当询问“这是角色吗”时,最好使用
composable
属性。也可以查看元对象的类型,如另一个答案中所建议的,但是在表示角色时涉及多个元对象(简称角色组、该组的参数和单个角色,以及支持组合过程的内部具体化表单)

因此,简单地检查事物是否是可组合的会更加健壮

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

你在哪里找到的?我在文件里什么地方都没看到。“我想我应该试一试。”布里安德福我看着拉库多的每一次行动。例如,我阅读了commit,其中
:transitive
成为默认值。如果您双关该角色,则此操作将失败。角色名将显示在类列表中。@briandfoy如果你双关它,它的字面意思是“已分类”。另外,我是在课堂上做的,而不是在一个物体上做的……因此我的第二个问题的性质非常特殊。@briandfoy和我答案中的黑客,这实际上把你的第一个问题变成了第二个问题的答案:-)这只是一个黑客,不管怎样。这两个都不符合我提到的原因。你认为哪一个是第一个问题的好答案?@briandfoy来自Brad Gilbert,他建议
^roles
,并指出
:transitive
选项。问题是,如果它使用NQP角色,那将失败。
> say (role RRR[::T] { }).HOW.archetypes.composable
1
> say RRR.HOW.archetypes.composable
1
> say RRR[Int].HOW.archetypes.composable
1