Functions

Functions and Functional Programming in Perl 6

Routines are the smallest means of code reuse in Perl 6. They come in several forms, most notably methods, which belong in classes and roles and are associated with an object; and functions (also called subroutines or subs, for short), which can be called independently of objects.

Subroutines default to lexical (my) scoping, and calls to them are generally resolved at compile time.

Subroutines can have a signature, also called parameter list, which specifies which, if any, arguments the signature expects. It can specify (or leave open) both the number and types of arguments, and the return value.

Introspection on subroutines is provided via Routine.

Defining/Creating/Using Functions

Subroutines

To basic way to create a subroutine is to use the sub declarator:

sub my-func { say "Look ma, no args!" }
my-func;

To have the subroutine take arguments, a signature goes between the subroutine's name and its body, in parentheses:

sub exclaim ($phrase) {
    say $phrase ~ "!!!!"
}
exclaim "Howdy, World";

By default, subroutines are lexically scoped. That is, sub foo {...} is the same as my sub foo {...} and is only defined within the current scope.

sub escape($str{
    # Puts a slash before non-alphanumeric characters 
    S:g[<-alpha -digit>] = "\\$/" given $str
}
 
say escape 'foo#bar?'# OUTPUT: «foo\#bar\?␤» 
 
{
    sub escape($str{
        # Writes each non-alphanumeric character in its hexadecimal escape 
        S:g[<-alpha -digit>] = "\\x[{ $/.ord.base(16}]" given $str
    }
 
    say escape 'foo#bar?' # OUTPUT: «foo\x[23]bar\x[3F]␤» 
}
 
# Back to original escape function 
say escape 'foo#bar?'# OUTPUT: «foo\#bar\?␤» 

Subroutines don't have to be named. If unnamed, they're called anonymous subroutines.

say sub ($a$b{ $a ** 2 + $b ** 2 }(34# OUTPUT: «25␤» 

But in this case, it's often desirable to use the more succinct block syntax. Subroutines and blocks can be called in place, as in the example above.

Blocks and Lambdas

Whenever you see something like { $_ + 42 }, -> $a, $b { $a ** $b }, or { $^text.indent($:spaces) }, that's Block syntax. It's used after every if, for, while, etc.

for 1234 -> $a$b {
    say $a ~ $b;
}
# OUTPUT: «12␤34␤» 

They can also be used on their own as anonymous blocks of code.

say { $^a ** 2 + $^b ** 2}(34# OUTPUT: «25␤» 

For block syntax details, see the documentation for the Block type.

Signatures

The parameters that a function accepts are described in its signature.

sub format(Str $s) { ... }
-> $a, $b { ... }

Details about the syntax and use of signatures can be found in the documentation on the Signature class.

Automatic Signatures

If no signature is provided but either of the two automatic variables @_ or %_ are used in the function body, a signature with *@_ or *%_ will be generated. Both automatic variables can be used at the same time.

sub s { dd @_%_ };
dd &s.signature # OUTPUT: «:(*@_, *%_)␤» 

Arguments

Arguments are supplied as a comma separated list. To disambiguate nested calls, use parentheses:

sub f(&c){ c() * 2 }# call the function reference c with empty parameter list 
sub g($p){ $p - 2 };
say(g(42), 45);       # pass only 42 to g() 

When calling a function, positional arguments should be supplied in the same order as the function's signature. Named arguments may be supplied in any order, but it's considered good form to place named arguments after positional arguments. Inside the argument list of a function call, some special syntax is supported:

sub f(|c){};
f :named(35);     # A named argument (in "adverb" form) 
f named => 35;    # Also a named argument 
f :35named;       # A named argument using abbreviated adverb form 
f 'named' => 35;  # Not a named argument, a Pair in a positional argument 
my \c = <a b c>.Capture;
f |c;             # Merge the contents of Capture $c as if they were supplied 

Arguments passed to a function are conceptually first collected in a Capture container. Details about the syntax and use of these containers can be found in the documentation on the Capture class.

When using named arguments, note that normal List "pair-chaining" allows one to skip commas between named arguments.

sub f(|c){};
f :dest</tmp/foo> :src</tmp/bar> :lines(512);
f :32:50:110z;   # This flavor of "adverb" works, too 
f :a:b:c;            # The spaces are also optional. 

Return values

Any Block or Routine will provide its last expression as a return value to the caller. If return or return-rw are called their parameter, if any, will become the return value. The default return value is Nil.

sub a { 42 };
sub b { say a };
b;
# OUTPUT: «42␤» 

Multiple return values are returned as a list or by creating a Capture. Destructuring can be used to untangle multiple return values.

sub a { 42'answer' };
put a.perl;
# OUTPUT: «(42, "answer")␤» 
 
my ($n$s= a;
put [$s$n];
# OUTPUT: «answer 42␤» 
 
sub b { <a b c>.Capture };
put b.perl;
# OUTPUT: «\("a", "b", "c")␤» 

Return Type Constraints

Perl 6 has many ways to specify a function's return type:

sub foo(--> Int)      {}say &foo.returns# OUTPUT: «(Int)␤» 
sub foo() returns Int {}say &foo.returns# OUTPUT: «(Int)␤» 
sub foo() of Int      {}say &foo.returns# OUTPUT: «(Int)␤» 
my Int sub foo()      {}say &foo.returns# OUTPUT: «(Int)␤» 

Attempting to return values of another type will cause a compilation error.

sub foo() returns Int { "a"}foo# Type check fails 

Note that Nil and Failure are exempt from return type constraints and can be returned from any routine, regardless of its constraint:

sub foo() returns Int { fail   }foo# Failure returned 
sub bar() returns Int { return }bar# Nil returned 

Multi-dispatch

Perl 6 allows you to write several routines with the same name but different signatures. When the routine is called by name, the runtime environment determines the proper candidate and calls it.

You declare each candidate with the multi declarator:

multi congratulate($name{
    say "Happy birthday, $name";
}
multi congratulate($name$age{
    say "Happy {$age}th birthday, $name";
}
 
congratulate 'Larry';       # OUTPUT: «Happy birthday, Larry␤» 
congratulate 'Bob'45;     # OUTPUT: «Happy 45th birthday, Bob␤» 

Dispatch can happen on the number of arguments (the arity), but also on the type:

multi as-json(Bool $d{ $d ?? 'true' !! 'false'}
multi as-json(Real $d{ ~$d }
multi as-json(@d)      { sprintf '[%s]'@d.map(&as-json).join(''}
 
say as-json([True42]);    # OUTPUT: «[true, 42]␤» 

Named parameters participate in the dispatch even if they are not provided in the call. Therefore a multi candidate with named parameters will be given precedence.

multi without any specific routine type always defaults to a sub, but you can use it on methods as well. The candidates are all the multi methods of the object:

class Congrats {
    multi method congratulate($reason$name{
        say "Hooray for your $reason$name";
    }
}
 
role BirthdayCongrats {
    multi method congratulate('birthday'$name{
        say "Happy birthday, $name";
    }
    multi method congratulate('birthday'$name$age{
        say "Happy {$age}th birthday, $name";
    }
}
 
my $congrats = Congrats.new does BirthdayCongrats;
 
$congrats.congratulate('promotion','Cindy'); # OUTPUT: «Hooray for your promotion, Cindy␤» 
$congrats.congratulate('birthday','Bob');    # OUTPUT: «Happy birthday, Bob␤» 

proto

proto is a way to formally declare commonalities between multi candidates. It acts as a wrapper that can validate but not modify arguments. Consider this basic example:

proto congratulate(Str $reasonStr $name|{*}
multi congratulate($reason$name{
   say "Hooray for your $reason$name";
}
multi congratulate($reason$nameInt $rank{
   say "Hooray for your $reason$name -- got rank $rank!";
}
congratulate('being a cool number''Fred');     # OK 
congratulate('being a cool number''Fred'42); # OK 
congratulate('being a cool number'42);         # Proto match error 

The proto insists that all multi congratulate conform to the basic signature of two strings, optionally followed by further parameters. The | is an un-named Capture parameter, and allows a multi to take additional arguments. The first two calls succeed, but the third fails (at compile time) because 42 doesn't match Str.

say &congratulate.signature # OUTPUT: «(Str $reason, Str $name, | is raw)␤» 

You can give the proto a function body, and place the {*} where you want the dispatch to be done.

# attempts to notify someone -- False if unsuccessful 
proto notify(Str $user,Str $msg{
   my \hour = DateTime.now.hour;
   if hour > 8 or hour < 22 {
      return {*};
   } else {
      # we can't notify someone when they might be sleeping 
      return False;
   }
}

{*} always dispatches to candidates with the parameters it's called with. Parameter defaults and type coercions will work but are not passed on.

proto mistake-proto(Str() $strInt $number = 42{*}
multi mistake-proto($str$number{ say $str.WHAT }
mistake-proto(742);  # OUTPUT: «(Int)␤» -- not passed on 
mistake-proto('test'); # fails -- not passed on 

Conventions and Idioms

While the dispatch system described above provides a lot of flexibility, there are some conventions that most internal functions, and those in many modules, will follow.

Slurpy Conventions

Perhaps the most important of these is the way slurpy list arguments are handled. Most of the time, functions will not automatically flatten slurpy lists. The rare exceptions are those functions that don't have a reasonable behavior on lists of lists; for example, chrs, or where there is a conflict with an established idiom, like pop being the inverse of push.

If you wish to match this look and feel, any Iterable argument must be broken out element-by-element using a **@ slurpy, with two nuances:

This can be achieved by using a slurpy with a + or +@ instead of **:

sub grab(+@a{ "grab $_".say for @a }

...which is shorthand for something very close to:

multi sub grab(**@a{ "grab $_".say for @a }
multi sub grab(\a{
    a ~~ Iterable and a.VAR !~~ Scalar ?? nextwith(|a!! nextwith(a,)
}

This results in the following behavior, which is known as the "single argument rule" and is important to understand when invoking slurpy functions:

grab(12);      # OUTPUT: «grab 1␤grab 2␤» 
grab((12));    # OUTPUT: «grab 1␤grab 2␤» 
grab($(12));   # OUTPUT: «grab 1 2␤» 
grab((12), 3); # OUTPUT: «grab 1 2␤grab 3␤» 

This also makes user-requested flattening feel consistent whether there is one sublist, or many:

grab(flat (12), (34));   # OUTPUT: «grab 1␤grab 2␤grab 3␤grab 4␤» 
grab(flat $(12), $(34)); # OUTPUT: «grab 1 2␤grab 3 4␤» 
grab(flat (12));           # OUTPUT: «grab 1␤grab 2␤» 
grab(flat $(12));          # OUTPUT: «grab 1␤grab 2␤» 

It's worth noting that mixing binding and sigilless variables in these cases requires a bit of finesse, because there is no Scalar intermediary used during binding.

my $a = (12);  # Normal assignment, equivalent to $(1, 2) 
grab($a);        # OUTPUT: «grab 1 2␤» 
my $b := (12); # Binding, $b links directly to a bare (1, 2) 
grab($b);        # OUTPUT: «grab 1␤grab 2␤» 
my \c = (12);  # Sigilless variables always bind, even with '=' 
grab(c);         # OUTPUT: «grab 1␤grab 2␤» 

Functions are First-Class Objects

Functions and other code objects can be passed around as values, just like any other object.

There are several ways to get hold of a code object. You can assign it to a variable at the point of declaration:

my $square = sub (Numeric $x{ $x * $x }
# and then use it: 
say $square(6);    # OUTPUT: «36␤» 

Or you can reference an existing named function by using the &-sigil in front of it.

sub square($x{ $x * $x };
 
# get hold of a reference to the function: 
my $func = &square

This is very useful for higher order functions, that is, functions that take other functions as input. A simple one is map, which applies a function to each input element:

sub square($x{ $x * $x };
my @squared = map &square,  1..5;
say join ''@squared;        # OUTPUT: «1, 4, 9, 16, 25␤» 

Infix Form

To call a subroutine with 2 arguments like an infix operator, use a subroutine reference surrounded by [ and ].

sub plus { $^a + $^b };
say 21 [&plus21;
# OUTPUT: «42␤» 

Closures

All code objects in Perl 6 are closures, which means they can reference lexical variables from an outer scope.

sub generate-sub($x{
    my $y = 2 * $x;
    return sub { say $y };
    #      ^^^^^^^^^^^^^^  inner sub, uses $y 
}
my $generated = generate-sub(21);
$generated(); # OUTPUT: «42␤» 

Here, $y is a lexical variable inside generate-sub, and the inner subroutine that is returned uses it. By the time that the inner sub is called, generate-sub has already exited. Yet the inner sub can still use $y, because it closed over the variable.

Another closure example is the use of map to multiply a list of numbers:

my $multiply-by = 5;
say join ''map { $_ * $multiply-by }1..5;     # OUTPUT: «5, 10, 15, 20, 25␤» 

Here, the block passed to map references the variable $multiply-by from the outer scope, making the block a closure.

Languages without closures cannot easily provide higher-order functions that are as easy to use and powerful as map.

Routines

Routines are code objects that conform to type Routine, most notably Sub, Method, Regex and Submethod.

They carry additional functionality in addition to what Block supplies: they can come as multis, you can wrap them, and exit early with return:

my $keywords = set <if for unless while>;
 
sub has-keyword(*@words{
    for @words -> $word {
        return True if $word (elem) $keywords;
    }
    False;
}
 
say has-keyword 'not''one''here';       # OUTPUT: «False␤» 
say has-keyword 'but''here''for';       # OUTPUT: «True␤» 

Here, return doesn't just leave the block inside which it was called, but the whole routine. In general, blocks are transparent to return, they attach to the outer routine.

Routines can be inlined and as such provide an obstacle for wrapping. Use the pragma use soft; to prevent inlining to allow wrapping at runtime.

sub testee(Int $iStr $s){
    rand.Rat * $i ~ $s;
}
 
sub wrap-to-debug(&c){
    say "wrapping {&c.name} with arguments {&c.signature.perl}";
    &c.wrap: sub (|args){
        note "calling {&c.name} with {args.gist}";
        my \ret-val := callwith(|args);
        note "returned from {&c.name} with return value {ret-val.perl}";
        ret-val
    }
}
 
my $testee-handler = wrap-to-debug(&testee);
# OUTPUT: «wrapping testee with arguments :(Int $i, Str $s)» 
 
say testee(10"ten");
# OUTPUT: «calling testee with \(10, "ten")␤returned from testee with return value "6.151190ten"␤6.151190ten» 
&testee.unwrap($testee-handler);
say testee(10"ten");
# OUTPUT: «6.151190ten␤» 

Defining Operators

Operators are just subroutines with funny names. The funny names are composed of the category name (infix, prefix, postfix, circumfix, postcircumfix), followed by a colon, and a list of the operator name or names (two components in the case of circumfix and postcircumfix).

This works both for adding multi candidates to existing operators and for defining new ones. In the latter case, the definition of the new subroutine automatically installs the new operator into the grammar, but only in the current lexical scope. Importing an operator via use or import also makes it available.

# adding a multi candidate to an existing operator: 
multi infix:<+>(Int $x"same"{ 2 * $x };
say 21 + "same";            # OUTPUT: «42␤» 
 
# defining a new operator 
sub postfix:<!>(Int $x where { $x >= 0 }{ [*1..$x };
say 6!;                     # OUTPUT: «720␤» 

The operator declaration becomes available as soon as possible, so you can recurse into a just-defined operator:

sub postfix:<!>(Int $x where { $x >= 0 }{
    $x == 0 ?? 1 !! $x * ($x - 1)!
}
say 6!;                     # OUTPUT: «720␤» 

Circumfix and postcircumfix operators are made of two delimiters, one opening and one closing.

sub circumfix:<START END>(*@elems{
    "start"@elems"end"
}
 
say START 'a''b''c' END;        # OUTPUT: «(start [a b c] end)␤» 

Postcircumfixes also receive the term after which they are parsed as an argument:

sub postcircumfix:<!! !!>($left$inside{
    "$left -> ( $inside )"
}
say 42!! 1 !!;      # OUTPUT: «42 -> ( 1 )␤» 

Blocks can be assigned directly to operator names. Use a variable declarator and prefix the operator name with a &-sigil.

my &infix:<ieq> = -> |l { [eql>>.fc };
say "abc" ieq "Abc";
# OUTPUT: «True␤» 

Precedence

Operator precedence in Perl 6 is specified relatively to existing operators. The traits is tighter, is equiv and is looser can be provided with an operator, the new operators precedence is related to. More then one trait can be applied.

For example, infix:<*> has a tighter precedence than infix:<+>, and squeezing one in between works like this:

sub infix:<!!>($a$bis tighter(&infix:<+>{
    2 * ($a + $b)
}
 
say 1 + 2 * 3 !! 4;     # OUTPUT: «21␤» 

Here, the 1 + 2 * 3 !! 4 is parsed as 1 + ((2 * 3) !! 4), because the precedence of the new !! operator is between that of + and *.

The same effect could have been achieved with:

sub infix:<!!>($a$bis looser(&infix:<*>{ ... }

To put a new operator on the same precedence level as an existing operator, use is equiv(&other-operator) instead.

Associativity

When the same operator appears several times in a row, there are multiple possible interpretations. For example:

1 + 2 + 3

could be parsed as

(1 + 2+ 3         # left associative 

or as

1 + (2 + 3)         # right associative 

For addition of real numbers, the distinction is somewhat moot, because + is mathematically associative.

But for other operators it matters a great deal. For example, for the exponentiation/power operator, infix:<**> :

say 2 ** (2 ** 3);      # OUTPUT: «256␤» 
say (2 ** 2** 3;      # OUTPUT: «64␤» 

Perl 6 has the following possible associativity configurations:

A Assoc Meaning of $a ! $b ! $c
L left ($a ! $b) ! $c
R right $a ! ($b ! $c)
N non ILLEGAL
C chain ($a ! $b) and ($b ! $c)
X list infix:<!>($a; $b; $c)

You can specify the associativity of an operator with the is assoc trait, where left is the default associativity.

sub infix:<§>(*@ais assoc<list> {
    '(' ~ @a.join('|'~ ')';
}
 
say 1 § 2 § 3;      # OUTPUT: «(1|2|3)␤» 

Traits

Traits are subroutines that run at compile time and modify the behavior of a type, variable, routine, attribute, or other language object.

Examples of traits are:

class ChildClass is ParentClass { ... }
#                ^^ trait, with argument ParentClass 
has $.attrib is rw;
#            ^^^^^  trait with name 'rw' 
class SomeClass does AnotherRole { ... }
#               ^^^^ trait 
has $!another-attribute handles <close>;
#                       ^^^^^^^ trait 

... and also is tighter, is looser, is equiv and is assoc from the previous section.

Traits are subs of the form trait_mod<VERB> , where VERB stands for the name like is, does or handles. It receives the modified thing as argument, and the name as a named argument. See Sub for details.

multi sub trait_mod:<is>(Routine $r:$doubles!{
    $r.wrap({
        2 * callsame;
    });
}
 
sub square($xis doubles {
    $x * $x;
}
 
say square 3;       # OUTPUT: «18␤» 

See type Routine for the documentation of built-in routine traits.

Re-dispatching

There are cases in which a routine might want to call the next method from a chain. This chain could be a list of parent classes in a class hierarchy, or it could be less specific multi candidates from a multi dispatch, or it could be the inner routine from a wrap.

In all those cases, you can use callwith to call the next routine in the chain with arguments of your own choice.

For example:

multi a(Any $x{
    say "Any $x";
    return 5;
}
multi a(Int $x{
    say "Int $x";
    my $res = callwith($x + 1);
    say "Back in Int with $res";
}
 
a 1;        # OUTPUT: «Int 1␤Any 2␤Back in Int with 5␤» 

Here, a 1 calls the most specific Int candidate first, and callwith re-dispatches to the less specific Any candidate.

Very often, a re-dispatch passes the same argument along that the caller received, so there is a special routine for that: callsame.

multi a(Any $x{
    say "Any $x";
    return 5;
}
multi a(Int $x{
    say "Int $x";
    my $res = callsame;
    say "Back in Int with $res";
}
 
a 1;        # OUTPUT: «Int 1␤Any 1␤Back in Int with 5␤» 

Another common use case is to re-dispatch to the next routine in the chain, and not do anything else afterwards. That's why we have nextwith and nextsame, which call the next routine with arbitrary arguments (nextwith) or with the same argument as the caller received (nextsame), but never return to the caller. Or to phrase it differently, the nextsame and nextwith variants replace the current callframe with the next candidate.

multi a(Any $x{
    say "Any $x";
    return 5;
}
multi a(Int $x{
    say "Int $x";
    nextsame;
    say "back in a";    # never executed, because 'nextsame' doesn't return 
}
 
a 1;        # OUTPUT: «Int 1␤Any 1␤» 

As mentioned earlier, multi subs are not the only situation in which callwith, callsame, nextwith and nextsame can be helpful. One is for dispatching to wrapped routines:

# enable wrapping: 
use soft;
 
# function to be wrapped: 
sub square-root($x{ $x.sqrt }
 
&square-root.wrap(sub ($num{
   nextsame if $num >= 0;
   1* callwith(abs($num));
});
 
say square-root(4);     # OUTPUT: «2␤» 
say square-root(-4);    # OUTPUT: «0+2i␤» 

The final use case is to re-dispatch to methods from parent classes.

class LoggedVersion is Version {
    method new(|c{
        note "New version object created with arguments " ~ c.perl;
        nextsame;
    }
}
 
say LoggedVersion.new('1.0.2');

If you need to make multiple calls to the wrapped code or to gain a reference to it, such as performing introspection it, you can use nextcallee.

sub power-it($x{ $x * $x }
sub run-it-again-and-again($x{
    my &again = nextcallee;
    again again $x;
}
 
&power-it.wrap(&run-it-again-and-again);
say power-it(5);    # OUTPUT: «625␤» 

Redispatch may be required to call a block that is not the current scope what provides nextsame and friends with the problem to referring to the wrong scope. Use nextcallee to capture the right candidate and call it at the desired time.

my \IOL = Lock.new;
&say.wrap-> |c {
    my &wrappee = nextcallee;
    IOL.protect: { &wrappee(|c}
});
for ^100 { say "oops" }

Coercion Types

Coercion types can help you to have a specific type inside a routine, but accept wider input. When the routine is called, the argument is automatically converted to the narrower type.

sub double(Int(Cool$x{
    2 * $x
}
 
say double '21';    # OUTPUT: «42␤» 
say double Any;     # Type check failed in binding $x; expected 'Cool' but got 'Any' 

Here, the Int is the target type to which the argument will be coerced, and Cool is the type that the routine accepts as input.

If the accepted input type is Any, you can abbreviate Int(Any) to Int().

The coercion works by looking for a method with the same name as the target type. You can define coercions for your own types like so:

class Bar {...}
 
class Foo {
   has $.msg = "I'm a foo!";
 
   method Bar {
       Bar.new(:msg($.msg ~ ' But I am now Bar.'));
   }
}
 
class Bar {
   has $.msg;
}
 
sub print-bar(Bar() $bar{
   say $bar.WHAT# OUTPUT: «(Bar)␤» 
   say $bar.msg;  # OUTPUT: «I'm a foo! But I am now Bar.␤» 
}
 
print-bar Foo.new;

Coercion types are supposed to work wherever types work, but Rakudo currently (2017.05) only implements them in signatures, for both parameters and return types.

sub MAIN

The sub with the special name MAIN is executed after all relevant phasers, and its signature is the means by which command line arguments can be parsed. Multi methods are supported and a usage method is automatically generated and displayed if no command line arguments are provided. All command line arguments are also available in @*ARGS, it can be mutated before being processed by MAIN.

The return value of MAIN is ignored. To provide an exitcode other then 0, call exit.

sub MAINInt :$length = 24,
           :file($datawhere { .IO.f // die "file not found in $*CWD" } = 'file.dat',
           Bool :$verbose )
{
    say $length if $length.defined;
    say $data   if $data.defined;
    say 'Verbosity ', ($verbose ?? 'on' !! 'off');
 
    exit 1;
}

sub USAGE

If no multi candidate of MAIN is found for the given command line parameters, the sub USAGE is called. If no such method is found, output a generated usage message.

sub MAIN(Int $i){ say $i == 42 ?? 'answer' !! 'dunno' }
 
sub USAGE(){
print Q:c:to/EOH/; 
Usage: {$*PROGRAM-NAME} [number]
 
Prints the answer or 'dunno'.
EOH
}