Traits

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|Traits,is (trait)

proto 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't-instantiate.new; 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:

  • CStruct corresponds to a struct in the C language. It is a composite data structure which includes different and heterogeneous lower-level data structures; see this for examples and further explanations.

  • CPPStruct, similarly, correspond to a struct in C++. However, this is Rakudo specific for the time being.

  • CPointer is a pointer in any of these languages. It is a dynamic data structure that must be instantiated before being used, can be used for classes whose methods are also native.

  • CUnion is going to use the same representation as an union in C; see this for an example.

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.

is implementation-detail|Traits,is implementation-detai trait

Available as of the 2020.05 release of the Rakudo compiler.

This trait is used by Raku language implementations and module authors to mark particular routines (including methods) as not meant to be a part of public API. While such routines can be found when looked up directly, they will not appear in results of introspection:

my &do-not-use-routine = CORE::<&DYNAMIC>;
    say CORE::.keys.grep(* eq '&DYNAMIC'); # OUTPUT: «()␤»

Such routines are not meant for use by users and their behavior and availability can be changed anytime.

As of the 2021.02 release of the Rakudo compiler, it is also possible to apply the is implementation-detail method on classes and roles.

method is-implementation-detail

method is-implementation-detail(--> True)

Applying this trait makes the is-implementation-detail method called on Code to return True, thus giving a hint to the user not to use it if they are not willing to maintain this code in case of changes for years to come:

my &fail-routine = &fail;
    unless &fail-routine.is-implementation-detail {
        say "&fail is not an implementation detail, can expect backward compatibility";
    }
sub PRIVATE-CALCULATION is implementation-detail { #`(Not safe to rely on this) }
    if &PRIVATE-CALCULATION.is-implementation-detail {
        say "You better not to rely on &PRIVATE-CALCULATION unless you really know what you are doing";
    }

See Also

Containers

A low-level explanation of Raku containers

Contexts and contextualizers

What are contexts and how to switch into them

Control flow

Statements used to control the flow of execution

Enumeration

An example using the enum type

Exceptions

Using exceptions in Raku

Functions

Functions and functional programming in Raku

Grammars

Parsing and interpreting text

Hashes and maps

Working with associative arrays/dictionaries/hashes

Input/Output the definitive guide

Correctly use Raku IO

Lists, sequences, and arrays

Positional data constructs

Metaobject protocol (MOP)

Introspection and the Raku object system

Native calling interface

Call into dynamic libraries that follow the C calling convention

Raku native types

Using the types the compiler and hardware make available to you

Newline handling in Raku

How the different newline characters are handled, and how to change the behavior

Numerics

Numeric types available in Raku

Object orientation

Object orientation in Raku

Operators

Common Raku infixes, prefixes, postfixes, and more!

Packages

Organizing and referencing namespaced program elements

Performance

Measuring and improving runtime or compile-time performance

Phasers

Program execution phases and corresponding phaser blocks

Pragmas

Special modules that define certain aspects of the behavior of the code

Quoting constructs

Writing strings and word lists, in Raku

Regexes

Pattern matching against strings

Sets, bags, and mixes

Unordered collections of unique and weighted objects in Raku

Signature literals

A guide to signatures in Raku

Statement prefixes

Prefixes that alter the behavior of a statement or a set of them

Data structures

How Raku deals with data structures and what we can expect from them

Subscripts

Accessing data structure elements by index or key

Syntax

General rules of Raku syntax

System interaction

Working with the underlying operating system and running applications

Date and time functions

Processing date and time in Raku

Unicode versus ASCII symbols

Unicode symbols and their ASCII equivalents

Unicode

Unicode support in Raku

Variables

Variables in Raku

Independent routines

Routines not defined within any class or role.

The Camelia image is copyright 2009 by Larry Wall. "Raku" is trademark of the Yet Another Society. All rights reserved.