class Sub
class Sub is Routine { }
A type for subroutines and operators. Subs are created with the sub
declarator keyword followed by an optional
identifier. This
short tutorial explains how operators are declared.
For details of a sub's parameter list, see Signature.
Note that subs that go by the same name as
coercers will not take precedence over
them. Use the &
-sigil to call them.
sub Int(Str $s){'what?'};
say [Int, Int('42'),&Int('42')];
# OUTPUT: «[(Int) 42 what?]»
Subs can be nested and scoped with my
and our
, whereby my
is the
default. A sub declared with my
cannot be reached from any outer scope. An
our
scoped sub will not redefine a sub of the same name in the outer scope.
Any sub can be accessed via a closure from any outer scope. For instance, in
this example
sub can-be-seener( $whatever ) {
my sub can-be-seen ( $objection ) {
return $whatever but $objection;
}
return &can-be-seen
}
my $objectioner = can-be-seener( "Really?");
say $objectioner(42).Int; # OUTPUT: «42»
$objectioner
will contain the can-be-seen
subroutine, even if it has been
declared in another scope; calling it with 42
will return "Really?"
with
the number 42 mixed in, as shown in the last sentence.
Operators
Operators are also Sub
s. Their definition includes
the category they belong to
and their
code, precedence and associativity.
The syntax used in their definition is an example of
extended identifiers.
Traits
A Trait
is a sub that is applied at compile time to various objects like
classes, routines or containers. It
is declared with the trait_mod
declarator followed by a colon and a string
literal containing the name of the trait. A single positional parameter defines
the type of the object that the trait is applied to. A single named argument
defines the secondary name and may carry arguments when the trait is called.
Traits are a special grammar category and are allowed to be placed after most
language object names or parameter lists.
say 'start';
multi trait_mod:<is>(Sub $s, :$foo){
say "⟨is foo⟩ has been called with ⟨$foo⟩ on {$s.WHICH}";
}
sub bar() is foo<oi‽> {
say 'bar has been called'
}
bar();
# OUTPUT: «⟨is foo⟩ has been called with ⟨oi‽⟩ on Sub|47563000startbar has been called»
Use destructuring to call traits with complex arguments.
multi trait_mod:<is>(Variable $a, :@foo [$firstpos, *@restpos, :$named, *%restnameds]) {
say [$firstpos, @restpos, $named, %restnameds]
}
my $x is foo[1,2,3,:named<a>, :2b, :3c] = 1
# OUTPUT: «[1 [2 3] a {b => 2, c => 3}]»
Despite its funky syntax, a trait is just a normal Sub
. We can apply traits
to it (or even themselves) and we can apply traits to objects at runtime.
multi trait_mod:<is> (Sub $s, :$foo) is foo {
say 'is foo called'
}
sub bar {}
&trait_mod:<is>(&bar, :foo);
# OUTPUT: «is foo calledis foo called»