Although not a new concept, functional programming has started to take a larger hold in the programming community. Features such as immutable variables and pure functions have proven helpful when we have to debug code, and higher-order functions make it possible for us to extract the inner workings of functions and write less code over time. All of this leads to more expressive code.
Who Is This Book For?
I wrote this book for anyone who is interested in functional programming or is looking to transition from an imperative style to a functional one. If youve been programming in an imperative or object-oriented style, my hope is that youll be able to pick up this book and start learning how to code in a functional one instead.
This book will teach you how to recognize patterns in an imperative style and then walk you through how to transition into a more functional one. We will approach this by looking at a fictional company called XXY and look at their legacy code. Well then refactor its legacy code from an imperative style into a functional one.
Were going to use a few different languages throughout this book:
Java I assume that you are familiar with the Java syntax. The version used in this book is 1.7.0. Groovy Using this language, we can keep most of our existing Java syntax; this helps us begin our transition into a fully functional language. Ill explain the main parts of the Groovy syntax as they are needed. The version used in this book is 2.0.4. Scala This is a fully functional language into which we will slowly transition. As with Groovy, I will explain the syntax as it is introduced. The version used in this book is 2.10.0.
Why No Java 8?
Some people might wonder why Im not including any Java 8 right now. As of this writing, Java 7 is the currently stable and widely used version. Because I want everyone, not just early adopters, to be able to take something from this book, I thought starting from Java 7 would be most accessible.
Those using Java 8 will be able to use some of the Groovy concepts, such as higher-order functions, without actually transitioning into Groovy.
Math Notation Review
Because functional programming is so closely tied to mathematics, lets go over some basic mathematical notation.
Functions in mathematics are represented with a name ( parameters ) = body style. The example in shows a very simple function. The name is f , the parameter list is x , the body is x + 1 , and the return is the numeric result of x + 1.
Equation 1. A simple math function
if
statements in math are represented by the array notation. shows a set of statements to be evaluated. The function abs(x)
will return x * -1
if our x
is less than 0
; otherwise, it will return x
.
Equation 2. A simple math if statement
We also use a summation , the sigma operator, in our notation. shows a simple summation. The notation says to have a variable n
starting at 0
(defined by the n=0
below the sigma) and continuing to x
(as defined by the x
above the sigma). Then, for each n
we add it to our sum (defined by the body, n
in our case, to the right of the sigma).
Equation 3. A simple math summation
Why Functional over Imperative?
There are quite a few paradigms, each with its own pros and cons. Imperative, functional, event-drivenall of these paradigms represent another way of programming. Most people are familiar with the imperative style because it is the most common style of programming. Languages such as Java and C languages are all imperative by design. Java incorporates object-oriented programming (OOP) into its language, but it still primarily uses an imperative paradigm.
One of the most common questions Ive heard during my time in software is why should I bother learning functional programming? Because most of my new projects have been in languages like Scala, the easiest response I can give is that is what the project is written in. But lets take a step back and actually answer the question in depth.
Ive seen quite a bit of imperative code that requires cryptographers to fully understand what it does. Generally, with the imperative style, you can write code and make it up as you go. You can write classes upon classes without fully understanding what the implementation will be. This usually results in a very large, unsustainable code base filled with an overuse of classes and spaghetti code.
Functional programming, on the other hand, forces us to better understand our implementation before and while were coding. We can then use that to identify where abstractions should go and reduce the lines of code we have written to execute the same functionality.
Why Functional Alongside OOP?
When we think of OOP, we normally think of a paradigm that is in a class of its own. But if we look at how we write OOP, the OOP is really used for encapsulation of variables into objects. Our code is actually in the imperative stylethat is, it is executed top to bottom. As we transition to functional programming, well see many more instances in which we just pass function returns into other functions.
Some people see functional programming as a replacement for OOP, but in fact well still use OOP so that we can continue using objects that can maintain methods. These methods, hoever, will usually call static versions that allow us to have purer and more testable functions. So, were not replacing OOP; rather, were using object-oriented design in a functional construct.
Why Functional Programming Is Important
Concepts such as design patterns in Java are so integral to our daily programming that its almost impossible to imagine life without them. So it is very interesting that, by contrast, the functional style has been around for many years but remains in the background as a main programming paradigm.
Why, then, is functional programming becoming so much more important today if its been around so long? Well, think back to the dot-com era, a time when any web presence was better than none. And what about general applications? As long as the application worked, nobody cared about the language or paradigm in which it was written.
Requirements and expectations today are difficult, so being able to closely mirror mathematical functions allows engineers to design strong algorithms in advance and rely on developers to implement those algorithms within the time frame required. The closer we bind ourselves to a mathematical underpinning, the better understood our algorithms will be. Functional programming also allows us to apply mathematics on those functions. Using concepts such as derivatives, limits, and integrals on functions can be useful when we are trying to identify where functions might fail.
Large functions are not very testable and also not very readable. Often, as software developers, we find ourselves presented with large chunks of functionality thrown into one function. But, if we extract the inner workings of these large, cumbersome functions into multiple, smaller, more understandable functions, we allow for more code reuse as well as higher levels of testing.