T M
class Sub
Error ReportCollection examples

Subroutine

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 [IntInt('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 Subs. 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 sub 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|47563000␤start␤bar 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 sub trait_mod:<is> (Sub $s:$foois foo {
    say 'is foo called'
}
sub bar {}
&trait_mod:<is>(&bar:foo);
# OUTPUT: «is foo called␤is foo called␤»