Book Image

Hands-On Functional Programming with C++

By : Alexandru Bolboaca
Book Image

Hands-On Functional Programming with C++

By: Alexandru Bolboaca

Overview of this book

Functional programming enables you to divide your software into smaller, reusable components that are easy to write, debug, and maintain. Combined with the power of C++, you can develop scalable and functional applications for modern software requirements. This book will help you discover the functional features in C++ 17 and C++ 20 to build enterprise-level applications. Starting with the fundamental building blocks of functional programming and how to use them in C++, you’ll explore functions, currying, and lambdas. As you advance, you’ll learn how to improve cohesion and delve into test-driven development, which will enable you in designing better software. In addition to this, the book covers architectural patterns such as event sourcing to help you get to grips with the importance of immutability for data storage. You’ll even understand how to “think in functions” and implement design patterns in a functional way. By the end of this book, you’ll be able to write faster and cleaner production code in C++ with the help of functional programming.
Table of Contents (23 chapters)
Free Chapter
1
Section 1: Functional Building Blocks in C++
7
Section 2: Design with Functions
12
Section 3: Reaping the Benefits of Functional Programming
17
Section 4: The Present and Future of Functional Programming in C++

Functional programming constructs are everywhere

Around 10 years after I finished the university functional programming course, I had a casual chat with my friend, Felix. As any two geeks, we would rarely see each other, but we had, for years, an ongoing conversation on instant messaging discussing all kinds of nerdy topics and, of course, programming.

Somehow, the topic of functional programming came up. Felix pointed out that one of my favorite and most enjoyable programming languages, LOGO, was, in fact, a functional programming language.

LOGO is an educational programming language whose main characteristic is utilization of so-called turtle graphics.

It was obvious in retrospect; here is how to write a function that draws a square in the KTurtle version of LOGO:

learn square {
repeat 4 {forward 50 turnright 90}
}

The result is shown in the following screenshot:

Can you see how we're passing two lines of code to the repeat function? That's functional programming! A fundamental tenet of functional programming is that code is just another type of data, which can be packed in a function and passed around to other functions. I used this construct in LOGO hundreds of times without making the connection.

This realization made me think: could there be other functional programming constructs that I've used without knowing? As it turns out, yes, there were. In fact, as a C++ programmer, you've most likely used them as well; let's take a look at a few examples:

int add(const int base, const int exponent){
return pow(base, exponent);
}

This function is a typical example of recommended C++ code. I first learned about the benefits of adding const everywhere from the amazing books of Bertrand Meyer: Effective C++, More Effective C++, and Effective STL. There are multiple reasons this construct works well. First, it protects the data members and parameters that shouldn't change. Second, it allows a programmer to reason more easily about what happens in the function by removing possible side effects. Third, it allows the compiler to optimize the function.

As it turns out, this is also an example of immutability in action. As we'll discover in the following chapters, functional programming places immutability at the core of the programs, moving all side effects to the edges of the program. We already know the basic construct of functional programming; to say that we use functional programming just means to use it much more extensively!

Here's another example from STL:

std::vector aCollection{5, 4, 3, 2, 1};
sort (aCollection.begin(), aCollection.end());

The STL algorithms have great power; this power comes from polymorphism. I'm using this term in a more fundamental sense than in OOP—it merely means that it doesn't matter what the collection contains, because the algorithm will still work fine as long as a comparison is implemented. I have to admit that when I first understood it, I was impressed by the smart, effective solution.

There's a variant of the sort function that allows the sorting of elements even when the comparison is not implemented, or when it doesn't work as we'd like; for example, when we are given a Name structure, as follows:

using namespace std;

// Parts of code omitted for clarity
struct Name{
string firstName;
string lastName;
};

If we'd like to sort a vector<Name> container by first name, we just need a compare function:

bool compareByFirstName(const Name& first, const Name& second){
return first.firstName < second.firstName;
}

Additionally, we need to pass it to the sort function, as shown in the following code:

int main(){
vector<Name> names = {Name("John", "Smith"), Name("Alex",
"Bolboaca")};

sort(names.begin(), names.end(), compareByFirstName);
}
// The names vector now contains "Alex Bolboaca", "John Smith"

This makes a kind of higher-order function. A high-level function is a function that uses other functions as parameters in order to allow higher levels of polymorphism. Congratulations—you've just used a second functional programming construct!

I will go as far as to state that STL is a good example of functional programming in action. Once you learn more about functional programming constructs, you'll realize that they are used everywhere in STL. Some of them, such as function pointers or functors, have been in the C++ language for a very long time. In fact, STL has stood the test of time, so why not use similar paradigms in our code as well?

There's no better example to support this statement other than the functional loops present in STL.