32,36 €
Learn functional programming and build robust applications using the latest functional features in C++
Key Features
Book Description
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.
What you will learn
Who this book is for
This book is for C++ developers who want to learn functional programming but have little to no knowledge of the paradigm. Although no prior knowledge of functional programming is necessary, basic C++ programming experience will help you understand key concepts covered in the book.
Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:
Seitenzahl: 426
Veröffentlichungsjahr: 2019
Copyright © 2019 Packt Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
Commissioning Editor:Richa TripathiAcquisition Editor:Shriram ShekharContent Development Editor:Manjusha MantriSenior Editor: Afshaan KhanTechnical Editor: Riddesh DawneCopy Editor: Safis EditingProject Coordinator:Prajakta NaikProofreader: Safis EditingIndexer: Rekha NairProduction Designer:Nilesh Mohite
First published: June 2019
Production reference: 1270619
Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK.
ISBN 978-1-78980-733-2
www.packtpub.com
Packt.com
Subscribe to our online digital library for full access to over 7,000 books and videos, as well as industry leading tools to help you plan your personal development and advance your career. For more information, please visit our website.
Spend less time learning and more time coding with practical eBooks and Videos from over 4,000 industry professionals
Improve your learning with Skill Plans built especially for you
Get a free eBook or video every month
Fully searchable for easy access to vital information
Copy and paste, print, and bookmark content
Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.packt.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.
At www.packt.com, you can also read a collection of free technical articles, sign up for a range of free newsletters, and receive exclusive discounts and offers on Packt books and eBooks.
With 20 years' experience in the software development industry, Alexandru Bolboaca has gone from being a junior C++ programmer to a technical lead and software architect, before becoming a technical coach and trainer. He has extensive experience in helping customers to improve the way they work, as well as their code and approach to testing. He is also the author of Usable Software Design, and the co-author of Coderetreat.
Trevor Hickey is a software engineer at Uber. He holds a bachelor's degree in computer science from Edinboro University of Pennsylvania. He has experience in literature peer review and specializes in computational pasigraphy. His research interests include pragmatics and relevance theory.
Will Brennan is a C++/Python software engineer based in London, with experience of working on high-performance image processing and machine learning applications.
Ryan Riley has been involved in the futures and derivatives industry for almost 20 years. He received a bachelor's degree and a master's degree from DePaul University in applied statistics. Doing his course work in math meant that he had to teach himself how to program, thereby forcing him to read more technical books on programming than he would otherwise have done. Ryan has worked with numerous AI libraries in various languages, and is currently using the Caffe2 C++ library to develop and implement futures and derivatives trading strategies at PNT Financial.
Andreas Oehlke is a professional full-stack software engineer. He holds a bachelor's degree in computer science and loves to experiment with software and hardware. His trademark has always been his enthusiasm and affinity for electronics and computers. His hobbies include game development, building embedded systems, sports, and making music. He currently works full time as a senior software engineer for a German financial institution. He has also worked as a consultant and game developer in San Francisco, CA. He is also the author of the book, Learning LibGDX Game Development.
If you're interested in becoming an author for Packt, please visit authors.packtpub.com and apply today. We have worked with thousands of developers and tech professionals, just like you, to help them share their insight with the global tech community. You can make a general application, apply for a specific hot topic that we are recruiting an author for, or submit your own idea.
Welcome to a hands-on tour of functional programming in C++! This book is about an old idea, that is, functional programming, and a classic programming language, that is, C++, finally uniting forces.
Functional programming has been around since the 1950s; however, due to its mathematical underpinnings, it has been of limited interest to mainstream software development for many years. With the advent of multicore CPUs and big data leading to the need for parallelization, and with programming language designers becoming more interested in immutability and lambdas, functional programming concepts have been gradually introduced in all major programming languages, including C#, Java, PHP, JavaScript, Python, and Ruby. C++ has never been far from functional programming, with features such as function pointers, functors, and the algorithms from STL allowing many programmers to take advantage of certain constructs. However, starting with C++ 11, we see the introduction of lambdas, and of higher-order functions such as all_of, any_of, and none_of. In C++ 17, we see more progress, with the introduction of map (implemented as transform). Additionally, the features coming in C++ 20 are very exciting; for example, the ranges library, which allows composable, lightweight, and lazily evaluated transformations, is a great addition to the standard.
This brings us to what you will learn from this book. Whether you are a seasoned programmer or a C++ beginner, you will learn about functional programming concepts, how to use them in C++, and why they are useful for managing and improving existing code bases. Every idea will be showcased with clear code samples and verified with unit tests; we highly encourage you to take these code samples and play around with them yourself.
Special effort has been put into ensuring that every idea is presented in a clear manner, and that a flow of understanding is followed; in other words, we've been looking at optimizing your learning experience. In order to do that, we have decided to exaggerate the use of certain constructs. For example, the sample code uses a lot of lambdas since we wanted to show how they can be used. We believe that the best way to learn functional programming is to fully dive into the world of lambdas and operations on lambdas. We expect the reader to separate this approach from a production approach; in fact, I advise you to experiment with these concepts on your own, then on small parts of production code, and only then use those that are promising to their full extent. To support this goal, we have documented multiple ways of using operations on functions so that you will possess enough tools to use in various contexts.
It's important to note that we made a calculated decision to present the C++ 17 standard in most of the book. We don't use external libraries (other than the unit testing library), and we stick to the standard features of the language and of Standard Template Library (STL). The focus is on functional programming concepts and on how to implement them using a minimalistic approach. The only exception is the last section of the book that looks at the future of C++ and STL. We did this because we believe that it's more important for you to understand the concepts and be ready to apply them with minimal tooling than to provide a multitude of implementation options. This has left out the ranges library for most of the book, the Boost library support for functional programming, and, most likely, other useful libraries that can extend or simplify the code. I will leave it to the reader to try them out for themselves and let us know how they worked.
This book is for programmers who already know C++ (including the language syntax, STL containers, and elements of templates) and who want to add more tools to their toolkit. You don't need to know anything about functional programming to read the book; we took care to explain every idea in a clear and practical manner.
You do, however, need to be curious about the set of tools coming from the world of functional programming. A hefty dose of experimentation will help you to make the most of this book, so I encourage you to play around with the code and to let us know what you find.
Chapter 1, An Introduction to Functional Programming, introduces you to the fundamental ideas of functional programming.
Chapter 2, Understanding Pure Functions, teaches you the fundamental building blocks of functional programming, functions that focus on immutability, and how to write them in C++.
Chapter 3, Deep Dive into Lambdas, focuses on lambdas and how to write them in C++.
Chapter 4, The Idea of Functional Composition, looks at how to compose functions with a higher order operation.
Chapter 5, Partial Application and Currying, teaches you how to use two fundamental operations on functions—partial application and currying in C++.
Chapter 6, Thinking in Functions – from Data in to Data out, introduces you to another way of organizing your code, enabling function-centric design.
Chapter 7, Removing Duplication with Functional Operations, is an overview of the Don't Repeat Yourself (DRY) principle, the types of code duplication and code similarities, and how to write more DRY code using functional operations such as composition, partial application, and currying.
Chapter 8, Improving Cohesion Using Classes, demonstrates how functions can evolve into classes and how classes can be turned into functions.
Chapter 9, Test-Driven Development for Functional Programming, looks at how to use Test-Driven Development (TDD) with functional programming and at how immutability and pure functions simplify tests.
Chapter 10, Performance Optimization, dives into specific methods of how to optimize the performance of function-centric design, including memoization, tail recursion optimization, and parallel execution.
Chapter 11, Property-Based Testing, looks at how functional programming enables a new paradigm of writing automated tests that enhances example-based testing with data generation.
Chapter 12, Refactoring to and through Pure Functions, explains how any existing code can be refactored to pure functions and then back into classes with minimal risk. It also looks at classic design patterns and a few functional design patterns.
Chapter 13, Immutability and Architecture – Event Sourcing, explains that immutability can move at the data storage level, looks at how to use event sourcing, and discusses its advantages and disadvantages.
Chapter 14, Lazy Evaluation Using the Ranges Library, dives into the awesome ranges library and demonstrates how to use it in C++ 17 and C++ 20.
Chapter 15, STL Support and Proposals, looks at STL functional features in the C++ 17 standard and at a few interesting additions to C++ 20.
Chapter 16, Standard Language Support and Proposals, closes the book with an overview of the fundamental building blocks of functional programming and the various options for using them in the C++ 17 standard.
This book assumes a good knowledge of the C++ syntax and of basic STL containers. However, it does not assume any knowledge of functional programming, functional constructs, category theory, or math. We've gone to great lengths to ensure that each concept is explained clearly and from a practical, programmer-centric perspective.
We strongly encourage you to play around with the code after reading the chapters or try to replicate the code from the samples after finishing a chapter. Even better, pick a coding kata (for example, from http://codingdojo.org/kata/) problem and try to solve it using the techniques from this book. You will learn much more by combining reading with toying with code than by simply reading the theory on its own.
Most of the content in this book requires you to think differently about the code structure and, sometimes, this will be contrary to what you are used to. However, we see functional programming as another tool in your toolkit; it doesn't contradict what you already know, instead, it just provides you with additional instruments to use with your production code. When and how you use them is your decision.
To run the code samples from the book, you will need g++ and the make command. Alternatively, you can run the samples using any compiler that supports C++ 17, but you will need to manually run each file. All the code samples compile and automatically run with make or make [specific example], and provide the output on the console with a few caveats that follow.
The memory optimization samples from Chapter 10, Performance Optimization, need to run with make allMemoryLogs or a specific target, require a keyboard press after each target run, and will create log files in the out/ folder, showing the evolution of allocated memory for the process. This will only work on Linux systems.
The reactive programming sample from Chapter 10, Performance Optimization and requires user input. Just input numbers and the program will compute in a reactive way whether they are prime or not. The program should receive inputs even while computing. The code samples from Chapter 16, Standard Language Support and Proposals, require a compiler that supports C++20; at this point, g++-8 is used. You will need to install g++-8 separately.
You can download the example code files for this book from your account at www.packt.com. If you purchased this book elsewhere, you can visit www.packt.com/support and register to have the files emailed directly to you.
You can download the code files by following these steps:
Log in or register at
www.packt.com
.
Select the
SUPPORT
tab.
Click on
Code Downloads & Errata
.
Enter the name of the book in the
Search
box and follow the onscreen instructions.
Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:
WinRAR/7-Zip for Windows
Zipeg/iZip/UnRarX for Mac
7-Zip/PeaZip for Linux
The code bundle for the book is also hosted on GitHub at https://github.com/PacktPublishing/Hands-On-Functional-Programming-with-Cpp. In case there's an update to the code, it will be updated on the existing GitHub repository.
We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!
Visit the following link to see the code being executed:
http://bit.ly/2ZPw0KH
There are a number of text conventions used throughout this book.
CodeInText: Indicates code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles. Here is an example: "In STL, it's implemented with the find_if function. Let's see it in action."
A block of code is set as follows:
class Number{ public: static int zero(){ return 0; } static int increment(const int value){ return value + 1; }}
When we wish to draw your attention to a particular part of a code block, the relevant lines or items are set in bold:
First call: 1,367 ns < 16,281 nsSecond call: 58,045 ns <
890,056 ns
Third call: 16,167 ns > 939 ns
Fourth call: 1,334 ns > 798 ns
Feedback from our readers is always welcome.
General feedback: If you have questions about any aspect of this book, mention the book title in the subject of your message and email us at [email protected].
Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you would report this to us. Please visit www.packt.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details.
Piracy: If you come across any illegal copies of our works in any form on the Internet, we would be grateful if you would provide us with the location address or website name. Please contact us at [email protected] with a link to the material.
If you are interested in becoming an author: If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, please visit authors.packtpub.com.
Please leave a review. Once you have read and used this book, why not leave a review on the site that you purchased it from? Potential readers can then see and use your unbiased opinion to make purchase decisions, we at Packt can understand what you think about our products, and our authors can see your feedback on their book. Thank you!
For more information about Packt, please visit packt.com.
In this section, we will learn about the basic building blocks of functional programming and how to use them in C++. First, we will look at what functional programming is and how it is different from and similar to object-oriented programming (OOP). Then, we will dive into the fundamental idea of immutability and learn how to write pure functions in C++—that is, functions that don't change state. We will then learn how to use lambdas and how to write pure functions using them.
Once we master those building blocks, we can move on to operations with functions. In functional programming, functions are data, so we can pass them around and make operations with them. We will learn about partial application and currying, two fundamental and closely-related operations. We will also see how to compose functions. These operations will take us from simple functions to very complex ones with just a few lines of plumbing code.
The following chapters will be covered in this section:
Chapter 1
,
An Introduction to Functional Programming
Chapter 2
,
Understanding Pure Functions
Chapter 3
,
Deep Dive into Lambdas
Chapter 4
,
The Idea of Functional Composition
Chapter 5
,
Partial Application and Currying
Why is functional programming useful? Functional programming constructs have popped up in all major programming languages in the past decade. Programmers have enjoyed their benefits—simplified loops, more expressive code, and simple parallelization. But there's more to it—decoupling from time, enabling opportunities to remove duplication, composability, and a simpler design. Higher adoption of functional programming (including the large-scale adoption of Scala in the financial sector) means more opportunities for you once you know and understand it. While we will take a deep dive into functional programming in this book to help you learn, remember that functional programming is another tool to add to your toolbox—one that you can choose to use when the problem and the context fits.
The following topics will be covered in this chapter:
An introduction to functional programming and an examination of how you've already been using functional constructs
Structured loops versus functional loops
Immutability
Object-oriented programming
(
OOP
)
versus functional design
Composability and removing duplication
The code works with g++ 7.3.0 and C++ 17; it includes a makefile for your convenience. You can find it in the GitHub repository (https://github.com/PacktPublishing/Hands-On-Functional-Programming-with-Cpp) in the Chapter01 directory.
My first experience with functional programming was at university. I was a 20-year-old geek who was interested in Sci-Fi, reading, and programming; programming was the highlight of my academic life. Everything to do with C++, Java, MATLAB, and a few other programming languages that we used was fun for me. Unfortunately, I can't say the same thing about the disciplines around electrical engineering, circuits, or compiler theory. I just wanted to write code!
Based on my interests, functional programming should have been a very fun course for me. Our teacher was very passionate. We had to write code. But something went wrong—I didn't click with what the teacher was telling us. Why were lists so interesting? Why was the syntax so backward and full of parentheses? Why would I use these things when it was much simpler to write the same code in C++? I ended up trying to translate all the programming constructs I knew from BASIC and C++ into Lisp and OCaml. It completely missed the point of functional programming, but I passed the course and forgot about it for many years.
I imagine that many of you can relate to this story, and I have a possible reason for this. I now believe that my teacher, despite being extremely passionate, used the wrong approach. Today, I understand that functional programming has a certain elegance at its core, due to its strong relationship with mathematics. But that elegance requires a sense of insightful observation that I didn't have when I was 20, that is, a sense that I was lucky to build on after years of various experiences. It's obvious to me now that learning functional programming shouldn't be related to the ability of the reader to see this elegance.
So, what approach could we use instead? Thinking about the past me, that is, the geek who just wanted to write code, there's only one way to go—look at the common problems in code and explore how functional programming reduces or removes them entirely. Additionally, start from the beginning; you've already seen functional programming, you've already used some of the concepts and constructs, and you might have even found them very useful. Let's examine why.
An important part of my job is to work with programmers and help them to improve the way they write code. To do so, I try my best to come up with simple explanations for complex ideas. I have one such explanation for software design. Software design is, for me, the way we structure the code such that we optimize it for business purposes.
I like this definition because it's plain and short. But one thing bugged me after I started experimenting with functional constructs; that is, functional programming leads to code such as the following:
const Sums sumsWithFunctionalLoopsSimplified(const vector<int>& numbers){ Sums theTotals( sum(filter(numbers, isEven)), sum(filter(numbers, isOdd)), sum(numbers) ); return theTotals; }
Writing similar code in OOP style would most likely mean creating classes and using inheritance. So, which style is better? Additionally, if software design is about code structure, is there an equivalence between the two styles?
First, let's take a look at what the two design styles really promote. What is OOP? For many years, I believed all the books that listed the following three properties of object-oriented languages:
Encapsulation
Inheritance
Polymorphism
Alan Kay, the thinker behind OOP, does not really agree with this list. For him, OOP is about communication between many small objects. As a biology major, he saw an opportunity to organize programs like the body organizes cells, and to allow objects to communicate much like cells do. He places more importance on objects over classes, and on communication over the commonly listed OOP properties. I would best summarize his position as follows: the dynamic relations in the system are more important than its static properties.
This changes a lot about the OOP paradigm. So, should classes match the real world? Not really. They should be optimized for the representation of the real world. Should we focus on having clear, well-thought out class hierarchies? No, since those are less important than the communication between objects. What is the smallest object that we can think of? Well, either a combination of data, or a function.
In a recent answer on Quora (https://www.quora.com/Isnt-getting-rid-of-the-evil-state-like-Haskells-approach-something-every-programmer-should-follow/answer/Alan-Kay-11), Alan Kay stated an interesting idea when answering a question on functional programming. Functional programming came from mathematics and from an effort to model the real world in order to enable artificial intelligence. This effort hit the following problem—Alex is in Bucharest and Alex is in London can both be true, but at different points in time. The solution to this modeling issue is immutability; that is, time becomes a parameter to functions, or a data member in the data structures. In any program, we can model data changes as time-bound versions of the data. Nothing stops us from modeling the data as small objects, and the changes as functions. Additionally, as we will see later, we can easily turn functions into objects and vice versa.
So, to summarize, there's no real tension between OOP as Alan Kay meant it and functional programming. We can use them together and interchangeably, as long as we focus on increasing the immutability of our code, and on small objects that communicate with one another. We'll discover, in the following chapters, how easy it is to replace a class with functions and vice versa.
But there are many ways to use OOP that are different from Alan Kay's vision. I've seen a lot of C++ code with my clients, and I've seen it all—big functions, huge classes, and deep inheritance hierarchies. Most of the time, the reason I'm called is because the design is too hard to change and because adding new features slows down to a crawl. Inheritance is a very strong relationship and overusing it leads to strong coupling, and, therefore, to code that's difficult to change. Long methods and long classes are harder to understand and harder to change. Of course, there are situations when inheritance and long classes make sense, but, in general, going for small objects with loose coupling enables changeability.
But classes can be reused, can't they? Can we do that with functions? Let's visit this topic next.
We've already covered a lot of interesting topics! You've just realized that you know the basics of functional programming. You can write immutable functions in C++ with the help of the const keyword. You've already used high-level functions from STL. Additionally, you don't have to forget anything about OOP, but, instead, just see it from a different perspective. Finally, we discovered how small immutable functions can be composed to offer complex functionality, and how they can become polymorphic with the help of C++ templates.
It's now time to take an in-depth look at the building blocks of functional programming and learn how to use them in C++. This includes pure functions, lambdas, and operations with functions such as functional composition, currying, or partial functional application.
What is an immutable function?
How do you write an immutable function?
How do immutable functions support code simplicity?
How do immutable functions support simple design?
What is a high-level function?
What example of high-level function can you give from STL?
What are the advantages of functional loops over structured loops? What are the potential disadvantages?