=begin pod :kind("Language") :subkind("Language") :category("fundamental")

=TITLE Traits

=SUBTITLE Compile-time specification of behavior made easy

In Raku,  I<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 C<trait_mod> keyword. They are listed, and explained,
next.

=head1 The X<C<is> trait|is (trait)>

Defined as

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

C<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.

=head2 C<is> applied to classes.

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

L<C<is DEPRECATED>|/type/Attribute#trait_is_DEPRECATED> can be applied to
classes, Attributes or Routines, marks them as deprecated and issues a message,
if provided.

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

The X<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.

=begin code
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;
=end code

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

=head2 C<is repr> and native representations.

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

=item X<CStruct> corresponds to a C<struct> in the C language. It is a
composite data structure which includes different and heterogeneous
lower-level data structures; see L<this|/language/nativecall#Structs>
for examples and further explanations.

=item X<CPPStruct>, similarly, correspond to a C<struct> in C++.
However, this is Rakudo specific for the time being.

=item X<CPointer> is a pointer in any of these languages. It is a
dynamic data structure that must be instantiated before being used, can
be L<used|/language/nativecall#Basic_use_of_pointers> for classes whose
methods are also native.

=item X<CUnion> is going to use the same representation as an C<union>
in C; see L<this|/language/nativecall#CUnions> for an example.

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

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

The L<metaobject protocol|/language/mop> 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.


=head2 C<is> on routines

The C<is> trait can be used on the definition of methods and routines to
establish L<precedence|/language/functions#Precedence> and
L<associativity|/language/functions#Associativity>. They act as a L<sub defined
using C<trait_mod>|/type/Sub#Traits> 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.

=head2 X<C<is implementation-detail>|is implementation-detail, traits> trait

Note: this trait has been available in Rakudo compiler starting from 2020.05 release.

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.

=head3 method is-implementation-detail

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

Applying this trait makes the C<is-implementation-detail> method called on
L<Code|/type/Code> to return C<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";
    }

=end pod

# vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6
