Traits and the Meta-Object Protocol

26.1 Traits

sub cached($n) is pure { $n ** 2 }           # pure: may be constant-folded
sub old-api() is DEPRECATED('new-api') { }   # warns when called
sub exported() is export { }                 # exported from a module
my @default is default(0);                   # variable trait
sub infix:<plus>($a, $b) is equiv(&infix:<+>) { $a + $b }   # operator precedence trait

# Custom traits
multi sub trait_mod:<is>(Routine $r, :$logged!) {
    $r.wrap(-> |c { note "Calling {$r.name}"; callsame });
}
sub important($x) is logged { $x * 2 }
say important(21);                           # prints "Calling important" to STDERR, then 42

26.2 Introspection

class Point { has $.x; has $.y; method norm { sqrt($!x² + $!y²) } }
say Point.^name;                     # Point
say Point.^methods(:local)».name;    # (norm x y ...)
say Point.^attributes».name;         # ($!x $!y)
say Point.^mro, ' ', Point.^parents;
say Point.HOW.^name;                 # Perl6::Metamodel::ClassHOW (metaclass)
say 42.^can('is-prime').so;
say &say.signature;
say Point.new(x => 3, y => 4).raku;  # Point.new(x => 3, y => 4)
say (sub ($a, :$b) { }).signature.params».name;

26.3 Building and Modifying Types at Run Time

my $class = Metamodel::ClassHOW.new_type(name => 'Dynamic');
$class.^add_method('hello', method { 'hello from a dynamic class' });
$class.^add_method('name-of', method { self.^name });
$class.^compose;
say $class.new.hello;

# Add a method to an existing class (augment requires MONKEY-TYPING)
use MONKEY-TYPING;
augment class Str { method shout { self.uc ~ '!' } }
say 'hey'.shout;                     # HEY!

# Wrapping routines
my $handle = &greet-wrapped.wrap(-> |c { "[" ~ callsame() ~ "]" });
sub greet-wrapped($n) { "Hello $n" }
say greet-wrapped('Ana');            # [Hello Ana]
&greet-wrapped.unwrap($handle);