How can I discover all the roles a Perl 6 type does?

perl 6 type system
perl 6 tutorial
perl6 cast
perl6 subset
perl 6 functional programming
perl6 struct
perl6 reference
perl6 enum

With .does I can check if a type has the role I already know. I'd like to get the list of roles. Inheritance has .^mro but I didn't see anything like that for roles in the meta model stuff.

Along with that, given a "type", how can I tell if it was defined as a class or a role?

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

By default it includes every role, including roles brought in by other roles. To only get the first level use :!transitive

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

syntax role, Documentation for syntax role assembled from the following types: you might have a class Bull , for all the bulls you keep around the house, and a class With this setup, your poor customers will find themselves unable to turn their Taurus  With .does I can check if a type has the role I already know. I'd like to get the list of roles. Inheritance has .^mro but I didn't see anything like that for roles in the meta model stuff.

There's already a good answer to the first question. About the second one, each meta-object has an archetypes method that in turn carries a range of properties of the types represented by that meta-type. This exists because Perl 6 is open to new meta-types (which might be easier to think about as "types of type"); probably the most widely used example of this today is OO::Monitors. The archetypes are more focused on what one can do with the type. For example:

> 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

The set of available properties can be introspected:

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

For example, "nominal" means "can this serve as a nominal type", and "augmentable" means "is it allowed to augment this kind of type". The things like "inheritalizable" mean "can I inheritalize such a type" - that is, turn it into a type that I can inherit from even if I can't inherit from this type. A role is not inheritable, but it is inheritalizable, and the inheritalize operation on it will produce the pun of the role. This is what is happening under the hood when writing something like class C is SomeRole { }, and means that not only is Perl 6 open to new types of type, but those new types of type can describe how they want to work, if at all, with inheritance and composition.

Being composable with does is probably the main defining property of a role, and thus the composable property is likely the best one to use when asking "is this a role". It is also possible to look at the type of the meta-object, as suggested in another answer, but there are multiple meta-objects involved in representing roles (the short name role group, a currying of that group with parameters, and an individual role, plus an internal concretization form that supports the composition process).

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

Thus it's rather more robust to simply check if the thing is composable.

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

Object orientation, Perl 6 provides strong support for Object Oriented Programming (OOP). All objects support methods from class Mu, which is the type hierarchy root. Roles are a collection of attributes and methods; however, unlike classes, roles are For example, if you've discovered an efficient method to ride cows, and are trying to  Perl 6 comes with a wealth of predefined types, which can be classified in two categories: regular and native types. Everything that you can store in a variable is either a native value or an object. That includes literals, types (type objects), code and containers.

Along with that, given a "type", how can I tell if it was defined as a class or a role?

A class is a type whose meta class is of type 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

Perl 6 and Parrot Essentials, Each class has its own vtable, which all objects of that class share. This means that with the right vtable methods every object can behave like a basic PMC type in addition to an object. This is used in part to implement Perl 6's roles. isn't 100% invisible, though you have to head off into the corner cases to find the cracks. The following crude benchmarks, with all the usual caveats about such things, show that Perl 6 can be faster than Perl 5 for similar tasks if the big weaponry is included, that is, if Perl 6 features are used to its full extent; at the same time, Perl 5 can be faster if only the bare bones are included.

Regarding your second question,

given a "type", how can I tell if it was defined as a class or a role?

I haven't found a direct way of doing that. Both classes and roles have Mu in their hierarchy, so that will not distinguish them. However, only classes get to be recognized by (the curiously named) MetaModel::ClassHOW. So we can hack something like this:

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;
}

Which will print:

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

, since calling ^mro on a role will raise an exception. That can be turned into a function for printing out which one is a role, and which is not.

Day 18: Roles, In Perl 6, classes retain the task of instance management. Re-use falls to roles. return ProductSearch::find($.battery-type); on its own. Instead, we must compose it into a class, using the does keyword. Unlike with inheritance and mix-ins, role composition puts all of the roles on a level playing field. Perl 6 compiler developers may also be interested in The Perl 6 Specification. Documentation for the different but related Perl 5 language can be found on the Perl 5 documentation website . Part of this official documentation has been translated into Chinese.

Perl 6 Deep Dive, Parrot is the first virtual machine aimed to be the base of the Perl 6 compiler. Parrot's goal was to create a virtual machine suitable for handling all the needs of Perl 6 from simple data types, Pugs main role in Perl 6 as of today is the vast test suite. You can find the project's repository at https://github.com/ fglock/​Perlito. Another important point to remember about managing roles is if you have multiple roles, you can't remove a permission from a lower role that would remove it from yourself. Important note on adding roles: the @everyone role now serves as the basic template for all added roles.

Perl 6 Fundamentals: A Primer with Examples, Projects, and Case , Perl 5 is developed by a separate community of enthusiasts, who keep an eye on Perl 6 to find features worth adopting into Perl 5. picture of the types involved, and later introduce type constraints to guard against future misuse of features such as class inheritance and role composition to manage code and regex reuse. Rakudo Perl 6 provides a very usable implementation of roles, and the Moose object system for Perl 5 allows you to use them as well. Roles are different from so-called traditional class-based or prototype-based or even multidispatch object systems in several important ways.

Perl 6 Types: Made for Humans, Perl 6 has gradual typing, which means you can either use types or avoid them. This functions both as data validation and as a safety net for garbage data generated by This can be useful to detect whether a method is called on the class or on the You don't need to declare a separate subset at all! This is the deprecated documentation of the Perl 6 language, currently known as Raku. Please use docs.raku.org from now on. This documentation is provided under the terms of the Artistic License 2.0 .

Comments
  • Where did you find that? I didn't see that anywhere in the docs. I guess I should have just tried it.
  • @briandfoy I look at every commit of Rakudo. So for example I read the commit where :transitive became the default.
  • Which one do you think is the good answer to the first question?
  • @briandfoy The one from Brad Gilbert suggesting .^roles and pointing out the :transitive option.
  • The problem is that if it's using NQP roles, that will fail.
  • This fails if you pun the role. The role name will show up in the class list.
  • @briandfoy if you pun it, it's literally "classed". Plus I'm doing it on the class, not on an object...
  • Hence the very specific nature of my second question.
  • @briandfoy and the hack in my answer, which actually turns around your first question to answer the second one :-) It's just a hack, anyway.
  • Neither of these are suitable for the reason I mentioned.