class Routine

Code object with its own lexical scope and return handling

class Routine is Block { }

A Routine is a code object meant for larger unities of code than Block. Routine is the common superclass for Sub (and therefore operators) and Method, the two primary code objects for code reuse.

Routines serve as a scope limiter for return (i.e. a return returns from the innermost outer Routine).

Routine is also the level at which multiness (multi subs and multi methods) are handled.

Trait is default

There is a special trait for Routines called is default. This trait is designed as a way to disambiguate multi calls that would normally throw an error because the compiler would not know which one to use. This means that given the following two Routines, the one with the is default trait will be called.

multi sub f() is default { say "Hello there" }
multi sub f() { say "Hello friend" }
f();   # OUTPUT: «"Hello there"␤» 

The is default trait can become very useful for debugging and other uses but keep in mind that it will only resolve an ambiguous dispatch between two Routines of the same precedence. If one of the Routines are narrower than another, then that one will be called. For example:

multi sub f() is default { say "Hello there" }
multi sub f(:$greet{ say "Hello " ~ $greet }
f();   # "Use of uninitialized value $greet..." 

In this example, the multi without is default was called because it was actually narrower than the Sub with it.

Subroutines can also be declared anon. See the documentation on the anon declarator for more information.


method name

method name(Routine:D: --> Str:D)

Returns the name of the sub or method.

method package

method package(Routine:D:)

Returns the package in which the routine is defined.

method multi

method multi(Routine:D: --> Bool:D)

Returns True if the routine is a multi sub or method. Note that the name of a multi sub refers to its proto and this method would return false if called on it. It needs to be called on the candidates themselves:

multi foo ($, $) {};
say &foo.multi;             # OUTPUT: «False␤» 
say &foo.candidates».multi# OUTPUT: «(True)␤» 

method candidates

method candidates(Routine:D: --> Positional:D)

Returns a list of multi candidates, or a one-element list with itself if it's not a multi

method cando

method cando(Capture $c)

Returns a possibly-empty list of candidates that can be called with the given Capture, ordered by narrowest candidate first. For methods, the first element of the Capture needs to be the invocant:

.signature.say for "foo".^can("comb")[0].cando: \(Cool"o");
# OUTPUT: «(Cool $: Str $matcher, $limit = Inf, *%_)␤» 

method wrap

method wrap(Routine:D: &wrapper)

Wraps (i.e. in-place modifies) the routine. That means a call to this routine first calls &wrapper, which then can (but doesn't have to) call the original routine with the callsame, callwith, nextsame and nextwith dispatchers. The return value from the routine is also the return value from the wrapper.

wrap returns an instance of a private class called WrapHandle, which you can pass to unwrap to restore the original routine.

method unwrap

method unwrap($wraphandle)

Restores the original routine after it has been wrapped with wrap. While the signature allows any type to be passed, only the WrapHandle type returned from wrap can usefully be.

method yada

method yada(Routine:D: --> Bool:D)

Returns True if the routine is a stub

say (sub f() { ... }).yada;      # OUTPUT: «True␤» 
say (sub g() { 1;  }).yada;      # OUTPUT: «False␤» 

trait is cached

multi sub trait_mod:<is>(Routine $r:$cached!)

NOTE: this feature is currently EXPERIMENTAL.

Causes the return value of a routine to be stored, so that when subsequent calls with the same list of arguments are made, the stored value can be returned immediately instead of re-running the routine.

Useful when storing and returning the computed value is much faster than re-computing it every time, and when the time saving trumps the cost of the use of more memory.

Even if the arguments passed to the routine are "reference types" (such as objects or arrays), then for the purpose of caching they will only be compared based on their contents. Thus the second invocation will hit the cache in this case:

say foo( [123] );   # runs foo 
say foo( [123] );   # doesn't run foo, uses cached value 
use experimental :cached;
sub nth-prime(Int:D $x where * > 0is cached {
    say "Calculating {$x}th prime";
    return (2..*).grep(*.is-prime)[$x - 1];
say nth-prime(43);
say nth-prime(43);
say nth-prime(43);

produces this output:

Calculating 43th prime

trait is pure

multi sub trait_mod:<is>(Routine $r:$pure!)

Marks a subroutine as pure, that is, it asserts that for the same input, it will always produce the same output without any additional side effects.

The is pure trait is a promise by the programmer to the compiler that it can constant-fold calls to such functions when the arguments are known at compile time.

sub syllables() is pure {
    say "Generating syllables";
    my @vowels = <a e i o u>;
    return  @vowels.append: <k m n sh d r t y> X~ @vowels;

You can mark function as pure even if they throw exceptions in edge cases or if they modify temporary objects; hence the is pure trait can cover cases that the compiler cannot deduce on its own. On the other hand, you might not want to constant-fold functions that produce a large return value (such as the string or list repetition operators, infix x and xx) even if they are pure, to avoid large precompilation files.

To see it an action with a particular compiler you can try this example:

BEGIN { say Begin }
say Start;
say (^100).map: { syllables().pick(2..5).join(""};
# Example output: 
# Begin 
# Generating syllables 
# Start 
# (matiroi yeterani shoriyuru... 

Essentially this allows the compiler to perform some operations at compile time. The benefits of constant-folding may include better performance, especially in cases when the folded code is precompiled.

In addition, using a pure function or operator in sink context (that is, where the result is discarded) may lead to a warning. The code

sub double($xis pure { 2 * $x };
say "anything";
# WARNING: «Useless use of "double(21)" in expression "double(21)" in sink context (line 2)» 

If you want to apply this trait to a multi, you need to apply it to the proto; it will not work otherwise, at least in versions 2018.08 and below.

trait is rw

multi sub trait_mod:<is>(Routine $r:$rw!)

When a routine is modified with this trait, its return value will be writable. This is useful when returning variables or writable elements of hashes or arrays, for example:

sub walk(\thing*@keysis rw {
    my $current := thing;
    for @keys -> $k {
        if $k ~~ Int {
            $current := $current[$k];
        else {
            $current := $current{$k};
my %hash;
walk(%hash'some''key'12= 'autovivified';
say %hash.perl;


("some" => {"key" => [Any, [AnyAny"autovivified"]]}).hash

Note that return marks return values as read only; if you need an early exit from an is rw routine, you have to use return-rw instead.

trait is export

multi sub trait_mod:<is>(Routine $r:$export!)

Marks a routine as exported to the rest of the world

module Foo {
    sub double($x) is export {
        2 * $x

import Foo;         # makes sub double available
say double 21;      # 42

From inside another file you'd say use Foo; to load a module and import the exported functions.

See Exporting and Selective Importing Modules for more details.


multi sub trait_mod:<is>(Routine:D $r:$DEPRECATED!)

Marks a routine as deprecated, optionally with a message what to use instead.

This code

sub f() is DEPRECATED('the literal 42'{ 42 }
say f();

produces this output:

Saw 1 occurrence of deprecated code.
Sub f (from GLOBALseen at:
  deprecated.p6line 2
Please use the literal 42 instead.
Please contact the author to have these occurrences of deprecated code
adaptedso that this message will disappear!

trait is hidden-from-backtrace

multi sub trait_mod:<is>(Routine:D:$hidden-from-backtrace!)

Hides a routine from showing up in a default backtrace. For example

sub inner { die "OH NOEZ" };
sub outer { inner() };

produces the error message and backtrace

  in sub inner at bt.p6:1
  in sub outer at bt.p6:2
  in block <unit> at bt.p6:3

but if inner is marked with hidden-from-backtrace

sub inner is hidden-from-backtrace { die "OH NOEZ" };
sub outer { inner() };

the error backtrace does not show it:

  in sub outer at bt.p6:2
  in block <unit> at bt.p6:3

Type Graph

Type relations for Routine
perl6-type-graph Routine Routine Block Block Routine->Block Mu Mu Any Any Any->Mu Callable Callable Code Code Code->Any Code->Callable Block->Code Method Method Method->Routine Macro Macro Macro->Routine Submethod Submethod Submethod->Routine Sub Sub Sub->Routine Regex Regex Regex->Method

Stand-alone image: vector

Routines supplied by class Code

Routine inherits from class Code, which provides the following routines:

(Code) method ACCEPTS

multi method ACCEPTS(Code:D: Mu $topic)

Usually calls the code object and passes $topic as an argument. However, when called on a code object that takes no arguments, the code object is invoked with no arguments and $topic is dropped. The result of the call is returned.

(Code) method arity

Defined as:

method arity(Code:D: --> Int:D)

Returns the minimum number of positional arguments that must be passed in order to call the code object. Any optional or slurpy parameters in the code object's Signature do not contribute, nor do named parameters.

sub argless() { }
sub args($a$b?{ }
sub slurpy($a$b*@c{ }
say &argless.arity;             # OUTPUT: «0␤» 
say &args.arity;                # OUTPUT: «1␤» 
say &slurpy.arity;              # OUTPUT: «2␤» 

(Code) method assuming

method assuming(Callable:D $self: |primers)

Returns a Callable that implements the same behaviour as the original, but has the values passed to .assuming already bound to the corresponding parameters.

my sub slow($n){ my $i = 0$i++ while $i < $n$i };
# takes only one parameter and as such wont forward $n 
sub bench(&c){ cnow - ENTER now };
say &slow.assuming(10000000).&bench# OUTPUT: «(10000000 7.5508834)␤» 

For a sub with arity greater than one, you can use Whatever * for all of the positional parameters that are not "assumed".

sub first-and-last ( $first$last ) {
    say "Name is $first $last";
my &surname-smith = &first-and-last.assuming*'Smith' );
&surname-smith.'Joe' ); # OUTPUT: «Name is Joe Smith␤» 

You can handle any combination of assumed and not assumed positional parameters:

sub longer-names ( $first$middle$last$suffix ) {
    say "Name is $first $middle $last $suffix";
my &surname-public = &longer-names.assuming**'Public'* );
&surname-public.'Joe''Q.''Jr.'); # OUTPUT: «Name is Joe Q. Public Jr.␤» 

Named parameters can be assumed as well:

sub foo { say "$^a $^b $:foo $:bar" }
&foo.assuming(13:42foo)(24:72bar); # OUTPUT: «13 24 42 72␤» 

And you can use .assuming on all types of Callables, including Methods and Blocks:

# We use a Whatever star for the invocant: 
my &comber = Str.^lookup('comb').assuming: *, /\w+/;
say comber 'Perl is awesome! Python is great! And PHP is OK too';
# OUTPUT: «(Perl Python PHP)␤» 
my &learner = {
    "It took me $:months months to learn $^lang"
}.assuming: 'Perl 6';
say learner :6months;  # OUTPUT: «It took me 6 months to learn Perl 6␤» 

(Code) method count

Defined as:

method count(Code:D: --> Real:D)

Returns the maximum number of positional arguments that may be passed when calling the code object. For code objects that can accept any number of positional arguments (that is, they have a slurpy parameter), count will return Inf. Named parameters do not contribute.

sub argless() { }
sub args($a$b?{ }
sub slurpy($a$b*@c{ }
say &argless.count;             # OUTPUT: «0␤» 
say &args.count;                # OUTPUT: «2␤» 
say &slurpy.count;              # OUTPUT: «Inf␤» 

(Code) method signature

Defined as:

multi method signature(Code:D: --> Signature:D)

Returns the Signature object for this code object, which describes its parameters.

sub a(Int $oneStr $two{};
say &a.signature# OUTPUT: «(Int $one, Str $two)␤» 

(Code) method Str

Defined as:

multi method Str(Code:D: --> Str:D)

Will produce a warning. Use .perl or .gist instead.

sub marine() { }
say ~&marine;    # OUTPUT: «marine␤» 
say &marine.Str# OUTPUT: «marine␤» 

(Code) method file

Defined as:

method file(Code:D: --> Str:D)

Returns the name of the file in which the code object was declared.

say &infix:<+>.file;

(Code) method line

Defined as

method line(Code:D: --> Int:D)

Returns the line number in which the code object was declared.

say &infix:<+>.line;

Routines supplied by role Callable

Routine inherits from class Code, which does role Callable, which provides the following routines:

(Callable) method CALL-ME

method CALL-ME(Callable:D $self: |arguments)

This method is required for postfix:«( )» and postfix:«.( )». It's what makes an object actually call-able and needs to be overloaded to let a given object act like a routine. If the object needs to be stored in a &-sigiled container, is has to implement Callable.

class A does Callable {
    submethod CALL-ME(|c){ 'called' }
my &a = A;
say a(); # OUTPUT: «called␤» 

(Callable) method Capture

Defined as:

method Capture()

Throws X::Cannot::Capture.