Permalink
Fetching contributors…
Cannot retrieve contributors at this time
87 lines (67 sloc) 3.06 KB
=begin pod
=TITLE class Sub
=SUBTITLE Subroutine
class Sub is Routine { }
A type for subroutines and operators. Subs are created with the C<sub>
declarator keyword followed by an optional
L<identifier|/language/syntax#Identifiers>. This
L<short tutorial explains how operators are declared|/language/optut>.
Note that subs that go by the same name as
L<coercers|/language/typesystem#Coercion> will not take precedence over
them. Use the C<&>-sigil to call them.
sub Int(Str $s){'what?'};
say [Int, Int('42'),&Int('42')];
# OUTPUT: «[(Int) 42 what?]␤»
X<|my (Sub)>X<|our (Sub)>
Subs can be nested and scoped with C<my> and C<our>, whereby C<my> is the
default. A sub declared with C<my> can not be reached from any outer scope. An
C<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␤»
C<$objectioner> will contain the C<can-be-seen> subroutine, even if it has been
declared in another scope; calling it with C<42> will return C<"Really?"> with
the number 42 mixed in, as shown in the last sentence.
=head1 Traits
X<|trait_mod (declarator)>
A C<Trait> is a sub that is applied at compile time to various objects like
classes, routines or L<containers|/language/phasers#index-entry-will_trait>. It
is declared with the C<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 places 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 L<destructuring|/type/Signature#Destructuring_Parameters> 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 C<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, :$foo) is foo {
say 'is foo called'
}
sub bar {}
&trait_mod:<is>(&bar, :foo);
# OUTPUT: «is foo called␤is foo called␤»
=end pod
# vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6