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

Functional Programming

Perl 6 is a multi-paradigm programming language. In the previous chapters, we mostly used traditional imperative programming. In this chapter, we will talk about the ways you can use a functional programming style with Perl 6.

These topics will be covered in this chapter:

  • Principles of functional programming
  • Re-writing traditional programs using recursion
  • Reduction operations
  • Higher-order functions, lambdas, and the whatever code blocks
  • Piping data with feed operators
  • Closures, currying, and dynamic scoping
  • Lazy and infinite lists and sequence generators

Before we go into any detail of the previously-listed topics, let us talk about what functional programming is.

What is functional programming?

Functional programming is the way of computing using a series of functions. Functions are understood here in the mathematical sense, not in the sense of subroutines in Perl 6. A very important principle of functional programming is that functions must have no side effects. In particular, that means that variables must be immutable—assigning a new value is forbidden.

All the topics that we will discuss in this chapter are the consequences of the preceding restrictions. It is important to realize that, for example, lambda functions are not the core essence of functional programming but are just one of the ways of following the main principle of having no side effects, such is changing some global variables that affect the result of the function.

Let us take a function f($x) and call it twice with the same argument. Will the second call return...

Using recursion

Our next program in this chapter is a simple loop that prints the numbers from 10 to 15 and calculates their sum. Let us first print in numbers. As we've seen in Chapter 5, Control Flow, there are different ways of making a loop in Perl 6. Choosing between them can lead us already in the direction of functional programming.

The loop cycle needs a loop counter:

my $sum = 0;
loop (my $n = 10; $n <= 15; $n++) {
$sum += $n;
}
say $sum; # 75

There are two variables that change their values in this program—$n and $sum. It is very easy to get rid of the $n counter, and thus re-assigning it a value:

my $sum = 0;
for 10..15 {
$sum += $_;
}
say $sum;

Now, we are using the $_ variable instead of $n and actually the for loop can use an explicit loop variable:

my $sum = 0;
for 10..15 -> $n {
$sum += $n;
}
say $sum;

The difference between this code and the...

Using reduction

In the previous section, we were calculating the sum of the numbers between 10 and 15. The program, after some transformations, became equivalent to the following one:

say 10 + (11 + (12 + (13 + (14 + 15))));

Each pair of parentheses here corresponds to the recursive call of the sum function. Calls of the function are replaced here with its implementation. This is one of the consequences of the restriction of the state-less approach. Would the function depend on the program state, it would not be possible to replace the function call with its implementation without knowing the values reflecting the state at different moments.

As parentheses do not change any order of execution here, let's remove them:

say 10 + 11 + 12 + 13 + 14 + 15;

What we see here is a list of all the values between 10 and 15 separated by the + operator. We have already met that in the...

Higher-order functions and lambdas

The [+] reduction operator that we have just seen in the previous section is performing the action of the + operator as many times as needed to add up all the elements of the provided data.

In Perl 6, there is an alternative way of doing reduction operations. There exists a built-in function reduce that expects a code block that will execute the action. First, we will use the function add($a, $b) that we created in Chapter 2, Writing Code:

sub add($a, $b) {
return $a + $b;
}

say reduce &add, 10..15;

The reduce function takes the reference to a function as the first argument and a flattened list of values. In &add, the ampersand before the name of the function tells Perl 6 that this is not a function call but a code reference to a function.

The reduce function is an example of the higher-order function. One of its arguments is another...

Piping data and feed operators

The grep, map, reduce, and sort functions are so powerful and easy to use that (together with other similar user-defined higher-order functions) they can handle many practical tasks in those areas where traditional imperative programming would organize it via loops.

Often, you will need to call one of the functions on the result that another function returned. Consider an example with the list of houses on a street. Some of these houses have to be painted, but you need to choose only those on the even side of the street, which has red facades, which were renovated more than five years ago. The task is to know how much paint you need.

Let us assume that the information about the properties of the house is contained in a data structure like this:

my @street = (
{
number => 1,
renovation_year => 2000,
storeys ...

Manipulating the scope

In this section, we will learn three techniques that can change the scope of variables. These are closures, currying, and dynamic scoping.

Closures

In Perl 6, lexical variables exist within their scope. Closures are functions that can extend that scope and let you access the lexical value, which were available at the place where the closure was defined. Let us consider an example of the counter that keeps the current state in a variable.

First, no closures are involved. The counter value is kept in a global variable:

my $counter = 0;

sub next-number() {
return $counter++;
}

say next-number(); # 0
say next-number(); # 1
say next-number(); # 2

Each time the next-number function is called, an increasing integer...

Creating and using iterators

Iterators are a powerful technique that provide data on demand and avoid manual counters. These are functions that return the next element of some sequence each time you call it. In the previous section, we already created the iterator new-counter, which generates incrementing integer numbers. Let us make something more complex:

sub make-iter(@data) {
my $index = 0;

sub {
return @data[$index++];
}
}

my &iter = make-iter(<red green blue orange>);

say iter; # red
say iter; # green
say iter; # blue
say iter; # orange

The make-iter function gets an array, installs the $index position to zero and returns a sub that will be used as an iterator. Next time the iter object is called, it returns the value at the current position and moves the internal pointer to the next element. After the data is exhausted, Nil will be returned.

Iterators...

Lazy and infinite lists

The example with a factorial can generate numbers as long as the memory limitations of the computer allow. Although we may want to calculate, say a factorial of 100, the program will not do that until we really need the value. No computational resources are spent if the result is not needed yet. This is the idea behind lazy calculations.

In Perl 6, the ... operator creates a sequence. The simplest case looks similar to how the range is created. A regular array will be created in the next example:

my @a = 1...100;
say @a.elems;

The @a array is created immediately and it gets all the 100 elements, which are integers from 1 to 100:

say @a[0];  # 1
say @a[1]; # 2

say @a[98];
# 99
say @a[99]; # 100

Contrarily, a lazy sequence created with the lazy keyword, will not populate the array:

my @b = lazy 1...100;

An attempt to get the size of it by calling @b.elems...

Summary

In this chapter, we were talking about functional programming. Perl 6, while not being a functional programming language, includes elements that can implement many features of such languages. We talked about recursions and reduction, about higher-order functions, lambda functions and the WhateverCode code blocks (those that use the * to ask Perl 6 to do what you want). We created a number of examples that use data piping, closures, currying, and dynamic scopes. And finally, we talked about infinite and lazy lists, and how to generate them.

The subject of the next chapter is reactive programming, which is another paradigm of programming that Perl 6 supports.

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 AU $19.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