Reader small image

You're reading from  Perl 6 Deep Dive

Product typeBook
Published inSep 2017
Reading LevelIntermediate
PublisherPackt
ISBN-139781787282049
Edition1st Edition
Languages
Right arrow
Author (1)
Andrew Shitov
Andrew Shitov
author image
Andrew Shitov

Andrew Shitov has been a Perl enthusiast since the end of the 1990s, and is the organizer of over 30 Perl conferences in eight countries. He worked as a developer and CTO in leading web-development companies, such as Art. Lebedev Studio, Booking dotCom, and eBay, and he learned from the "Fathers of the Russian Internet", Artemy Lebedev and Anton Nossik. Andrew has been following the Perl 6 development since its beginning in 2000. He ran a blog dedicated to the language, published a series of articles in the Pragmatic Perl magazine, and gives talks about Perl 6 at various Perl events. In 2017, he published the Perl 6 at a Glance book by DeepText, which was the first book on Perl 6 published after the first stable release of the language specification.
Read more about Andrew Shitov

Right arrow

Subroutines

Subroutines are one of the fundamental concepts in programming. They help organize better-structured code, which is also easy to reuse. Perl 6 offers great support for subroutines and many interesting related features. In Perl 6, subroutines are often called subs.

We will cover the following topics in this chapter:

  • Creating a subroutine
  • Calling a subroutine
  • Typed arguments
  • Signature properties
  • Passing arguments by value or by reference
  • Operators as subroutines
  • Nested subroutines
  • References to subroutines
  • Overloading subroutines and multiple dispatch
  • Anonymous subroutines and lambdas
  • Variable placeholders

Creating and calling subroutines

The sub keyword creates a subroutine. A typical subroutine has a name, a list of formal parameters, and a body. However, both the name and the parameter list are optional. In Chapter 1, What is Perl 6?, we already created a subroutine to add two numbers. Let's recall it here:

sub add($x, $y) {
    return $x + $y;
}

Here, add is the name, which will later be used to call a sub. It is followed by a list of the sub's parameters—($x, $y). The body of the subroutine is enclosed inside a pair of curly braces—{return $x + $y;}.

To call a subroutine, use the name again and pass the actual parameters in parentheses:

my $a = 17;
my $b = 71;
my $sum = add($a, $b);
say "Sum of $a and $b is $sum"; # Sum of 17 and 71 is 88

There are two ways a sub can return a value. The first we just saw in the add function. It uses an explicit...

Type constraints

In Perl 6, you don't have to declare a type of a variable, but you can do so if you want to. The same rules apply to the arguments of a sub and to its return value.

Typed parameters

In the previous sections of this chapter, we did not say anything about the types of the $a and $b parameters of the add function. The code of the sub assumes that the arguments should be numeric because the + operator is used. Calling a function with two strings as arguments, for example, add('Hello', 'World'), will generate the following runtime error:

Cannot convert string to number: base-10 number must begin with valid digits or '.' in 'Hello' (indicated by )

This exception happens...

Multi subs

The signature is an important property of a sub. It not only helps to check the types of the arguments, but Perl 6 also uses it to control the number of arguments passed. For example, declare a function for summation that takes three parameters, but call it with only two arguments:

sub add($x, $y, $z) {
    return $x + $y + $z;
}

say add(1, 2);

This program does not work. Again, signature is our friend:

===SORRY!=== Error while compiling add.pl
Calling add(Int, Int) will never work with declared signature ($x, $y, $z)
at add.pl:5

So, we see that when deciding which function to call, Perl 6 takes into account the number of the arguments as well as their types together with the name of the sub. A programmer can benefit from this feature by creating different versions of the function, which share the same name. The distinction between them will be resolved via their signatures...

Nested subroutines

Subroutines can be nested. In other words, you may define a sub inside another sub. Let's see it in the next example, which lists the present tense forms of regular English verbs:

sub list_verb_forms($verb) {
    sub make_form($base, $pronoun) {
        my $form = $base;
        # Adds the 's' ending for he, she, and it.
        # The check uses a regular expression.
        # We cover regular expressions in Chapter 11, Regexes.
        $form ~= 's' if $pronoun ~~ /^ [ he | she | it ] $/;

        return "$pronoun $form";
    }

    my @pronouns = <I we you he she it they>;

    for @pronouns -> $pronoun {
        say make_form($verb, $pronoun);
    }
}

list_verb_forms('read');

The result of this program is exactly what we wanted, as you can see here:

I read
we read
you read
he reads
she reads
it reads
they...

Creating operators

Operators in Perl 6 are subroutines. In most cases, operator subs are multisubs. Consider, for example, the + operator. Its semantic is to add two values, which, in turn, can be of different types. You may ask Perl 6 to add two integers, floating points, or complex numbers. Or, the operands may be of different types in the same call, say, when adding a complex number and an integer. The same + operator also works fine with the types representing dates. To achieve all of this flexibility, Perl 6 uses multi subs.

Let's briefly lurk into the source code of Rakudo and search for a few definitions of the + operator:

multi sub infix:<+>(Int:D \a, Int:D \b)
multi sub infix:<+>(Num:D \a, Num:D \b)

multi sub infix:<+>(Complex:D \a, Complex:D \b) 
multi sub infix:<+>(Complex:D \a, Num(Real) \b)
multi sub infix:<+>(Num(Real) \a...

Passing functions as arguments

Functions in Perl 6 can be passed to other functions as arguments. A typical example is a sort algorithm that needs a function to compare two values. Depending on the data types, it can be different functions that know how to compare the values of that type.

Let's examine the following tiny example:

sub less($a, $b) {$a < $b}
sub more($a, $b) {$a > $b}

sub compare($a, $b, $f) {
    $f($a, $b) 
}

say compare(10, 20, &less); # True
say compare(10, 20, &more); # False

The main code calls the compare sub with three arguments—two integer numbers and a reference to one of the functions—&less or &more. An ampersand before the name tells us that a function should not be called at this point (remember that, in Perl 6, parentheses are not required when calling a function).

Inside the compare function, the third argument...

Anonymous subs

A subroutine without a name is called an anonymous sub. You cannot call it by name, but it is still possible to run it via a handle, which, for example, is stored in a variable. All the attributes of a regular sub, such as a signature and a body, are defined in the same way as the normal subs.

In the following code, we will create an anonymous sub and save it in the $add variable; a space before the signature is required:

my $add = sub ($x, $y) {$x + $y}
say $add(10, 20); # 30

Perl 6 allows a mixture of regular and anonymous subs. The anon keyword creates an anonymous sub out of the regular one, so its name can still be used to call it. First, look at the sub, which can be used both as an anonymous one and be called by its name:

my $add = sub add ($x, $y) {$x + $y}
say $add(1, 2); # using anonymous sub
say add(3, 4);  # using regular sub call by name

Now, let us...

Summary

Subroutines, or subs, are one of the keystones of Perl 6. In this chapter, you learned how to create and use subroutines. We examined in detail the properties of the sub's parameters, such as passing parameters by copy, allowing read-and-write parameters, defining the default value, or providing parameters that are optional. You looked at the slurpy parameters and flattening arrays, learned how to constrain the type of both the arguments, and then return value.

On top of that, other applications of the subroutines were discussed. Namely, we talked about overloading subs with the multi keyword, looked at how new operators can be created and embedded in the language, and how to pass functions to other functions. And, finally, we took a brief look at anonymous functions and pointy code blocks.

In the next chapter, we'll talk about modules, which are the next level...

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Perl 6 Deep Dive
Published in: Sep 2017Publisher: PacktISBN-13: 9781787282049
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €14.99/month. Cancel anytime

Author (1)

author image
Andrew Shitov

Andrew Shitov has been a Perl enthusiast since the end of the 1990s, and is the organizer of over 30 Perl conferences in eight countries. He worked as a developer and CTO in leading web-development companies, such as Art. Lebedev Studio, Booking dotCom, and eBay, and he learned from the "Fathers of the Russian Internet", Artemy Lebedev and Anton Nossik. Andrew has been following the Perl 6 development since its beginning in 2000. He ran a blog dedicated to the language, published a series of articles in the Pragmatic Perl magazine, and gives talks about Perl 6 at various Perl events. In 2017, he published the Perl 6 at a Glance book by DeepText, which was the first book on Perl 6 published after the first stable release of the language specification.
Read more about Andrew Shitov