Introduction - Becoming Functional (2014)

Becoming Functional (2014)

Chapter 1. Introduction

Our first step before we get into actual examples is to look at what defines functional programming. Specifically, we will look at the components that make up functional programming and how they relate to mathematics.

NOTE

Functional programming traces its roots all the way back to LISP, although the paradigm name itself wasn’t truly coined until John Backus delivered his 1977 Turing Award–winning paper “Can Programming Be Liberated From the von Neumann Style? A Functional Style and Its Algebra of Programs.” In his lecture, Backus discusses multiple points about applications being built as combinations of algebraic equations.

Overview of Concepts in Functional Programming

Although there is still some disagreement about what functional programming is, there are a few features that are generally agreed to be part of it:

§ First-class functions

§ Pure functions

§ Recursion

§ Immutable variables

§ Nonstrict evaluation

§ Statements

§ Pattern matching

First-Class Functions

First-class functions can either accept another function as an argument or return a function. Being able to create functions and return them or pass them to other functions becomes extremely useful in code reusability and code abstractions.

Pure Functions

Pure functions are functions that have no side effects. Side effects are actions a function may perform that are not solely contained within the function itself. When we think about side effects, we normally think about other functions, such as println or mutating a global variable. We can also see this when we pass in a variable and mutate it directly inside of that function.

Recursion

Recursion allows us to write smaller, more concise algorithms and to operate by looking only at the inputs to our functions. This means that our function is concerned only with the iteration it is on at the moment and whether it must continue.

Immutable Variables

Immutable variables, once set, cannot be changed. Although immutability seems very difficult to do, given the fact that the state must change within an application at some point, we’ll see ways that we can accomplish it.

Nonstrict Evaluation

Nonstrict evaluations allow us to have variables that have not been computed yet. Strict evaluations—assigning a variable as soon as it is defined—are what we are used to. Nonstrict means that we can have a variable that does not get assigned (computed) until the first time it is referenced.

Statements

Statements are evaluable pieces of code that have a return value. Think about if statements that have a return value of some kind. Each line of code should be considered a statement, meaning there are very few side effects within the application itself.

Pattern Matching

Pattern matching doesn’t really appear in mathematics, but assists functional programming in decreasing the need for specific variables. In code we usually encapsulate a group of variables together inside of an object. Pattern matching allows us to better type-check and extract elements from an object, making for simpler and more concise statements with less need for variable definitions.

Functional Programming and Concurrency

Concurrency enables us to do processing in parallel, and we won’t cover much about it here because the topic could fill its own book. Some people believe that functional programming actually solves concurrency issues, but this is not actually the case; rather, some of the concepts of functional programming help us to create more well-defined patterns to handle concurrency.

For example, techniques such as message passing help us to create more independent threads by allowing a thread to receive messages without causing another thread to block before it is received.

In addition, features such as immutability help us to define global states and allow global state transitions as a whole rather than partial state changes or major synchronizations between threads.

Conclusion

This chapter was intended as a high-level overview of the important concepts of functional programming. At this point you’re probably wondering “how can I actually get started using these concepts?” As we go through this book, we’ll look at how to implement these features in your code.

In each chapter, I’ll introduce a concept, and then we’ll work to refactor and implement it in our example code for the ficticious company XXY. The examples have no “driver code.” I assume that everyone reading this book can write simple Java main() functions to test out the code we’re writing. I’m doing this for two reasons.

First, I really want you to write the code and test it out yourself; just reading the examples isn’t going to help you understand the concepts or help you become a better functional programmer.

Second, I want to draw attention away from the driver code. Sometimes, when writing more extraneous code to actually call the code that we’re refactoring, we either forget to refactor the driver code or tend to write too much. Would it really be useful to create a set of driver code to create 10 or 20 Customer objects?

Each language example is compilable and runnable. The language examples will not rely on external packages. One of the things I truly dislike about some concept books or language books is that normally the author will push you to download third-party packages. In contrast, the goal of this book is to teach you how to deal with functional concepts using the core language.