Compile-time specification of behavior made easy

In Raku, traits are compiler hooks attached to objects and classes that modify their default behavior, functionality or representation. As such compiler hooks, they are defined in compile time, although they can be used in runtime.

Several traits are already defined as part of the language or the Rakudo compiler by using the trait_mod keyword. They are listed, and explained, next.

The is trait

Defined as

proto sub trait_mod:<is>(Mu $|{*}

is applies to any kind of scalar object, and can take any number of named or positional arguments. It is the most commonly used trait, and takes the following forms, depending on the type of the first argument.

is applied to classes.

The most common form, involving two classes, one that is being defined and the other existing, defines parenthood. A is B, if both are classes, defines A as a subclass of B.

is DEPRECATED can be applied to classes, Attributes or Routines, marks them as deprecated and issues a message, if provided.

Several instances of is are translated directly into attributes for the class they refer to: rw, nativesize, ctype, unsigned, hidden, array_type.

The Uninstantiable representation trait is not so much related to the representation as related to what can be done with a specific class; it effectively prevents the creation of instances of the class in any possible way.

constant @IMM = <Innie Minnie Moe>;
class don't-instantiate is repr('Uninstantiable'{
    my $.counter;
    method imm () {
        return @IMM$.counter++ mod @IMM.elems ];
say don't-instantiate.imm for ^10;

Uninstantiable classes can still be used via their class variables and methods, as above. However, trying to instantiate them this way: my $do-instantiate = don'; will yield the error You cannot create an instance of this type (don't-instantiate).

is repr and native representations.

Since the is trait refers, in general, to the nature of the class or object they are applied to, they are used extensively in native calls to specify the representation of the data structures that are going to be handled by the native functions via the is repr suffix; at the same time, is native is used for the routines that are actually implemented via native functions. These are the representations that can be used:

On the other hand, P6opaque is the default representation used for all objects in Raku.

class Thar {};
say Thar.REPR;    #OUTPUT: «P6opaque␤»

The metaobject protocol uses it by default for every object and class unless specified otherwise; for that reason, it is in general not necessary unless you are effectively working with that interface.

is on routines

The is trait can be used on the definition of methods and routines to establish precedence and associativity. They act as a sub defined using trait_mod which take as argument the types and names of the traits that are going to be added. In the case of subroutines, traits would be a way of adding functionality which cuts across class and role hierarchies, or can even be used to add behaviors to independently defined routines.