What is Functional Programming?

Defining “Functional Programming”

It’s surprisingly hard to find a consistent definition of functional programming.

I share links to many definitions at the end of this lesson, but I think you can define FP with just two statements:

  1. FP is about writing software applications using only pure functions.
  2. When writing FP code you only use immutable values — val fields in Scala.

And when I say “only” in those sentences, I mean only.

You can combine those two statements into this simple definition:

Functional programming is a way of writing software applications using only pure functions and immutable values.

Of course that definition includes the term “pure functions,” so see my previous videos for that definition.

Note 1: Higher-Order Functions are a great FP language feature

I don’t include HOFs in my definition of functional programming. In the end, HOFs are a terrific FP language feature, and they make Scala a much better FP language than Java, but it’s still just a language feature, not a part of the core definition of functional programming.

Note 2: Recursion is a by-product

Sometimes you’ll see a definition of FP that states, “Recursion is a requirement of functional programming.” While it’s true that pure FP languages use recursion, the need for recursion is a by-product of my FP definition.

Once you dig into FP, you’ll see that if you only use pure functions and immutable values, the only way you can do things like “calculate the sum of a list” is by using recursion. Therefore, it’s a by-product of my definition, not a part of the definition.

Proof: Wikipedia’s FP definition

When you google “functional programming definition,” the first link that currently shows up is from Wikipedia, and their definition of FP backs up my statements. The first line of their definition begins like this:

“In computer science, functional programming is a programming paradigm — a style of building the structure and elements of computer programs — that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data.”

So, yes, FP is made of (a) pure functions and (b) immutable data. (Their “mathematical functions” are equivalent to my pure functions.)

As proof for another assertion I made earlier, that Wikipedia page also elaborates on features that make an FP language easier to use — such as being able to treat functions as values — where they state, “Programming in a functional style can also be accomplished in languages that are not specifically designed for functional programming.” (Think Java.)

Proof: A wonderful quote from Mary Rose Cook

When I first started learning FP, I was aware that pure functions were important, but this point was really driven home when I came across an article titled A Practical Introduction to Functional Programming by Mary Rose Cook.

Ms. Cook used to work at the Recurse Center (formerly known as “Hacker School”) and now works at Makers Academy, and in her “Practical Introduction to FP” essay, she refers to using only pure functions as a Guide Rope to learning FP:

“When people talk about functional programming, they mention a dizzying number of ‘functional’ characteristics. They mention immutable data, first class functions, and tail call optimisation. These are language features that aid functional programming.”

“They mention mapping, reducing, pipelining, recursing, currying and the use of higher order functions. These are programming techniques used to write functional code.”

“They mention parallelization, lazy evaluation, and determinism. These are advantageous properties of functional programs.”

“Ignore all that. Functional code is characterised by one thing: the absence of side effects. It (a pure function) doesn’t rely on data outside the current function, and it doesn’t change data that exists outside the current function. Every other ‘functional’ thing can be derived from this property. Use it as a guide rope as you learn.”

When she writes about the “absence of side effects,” she’s referring to building applications from pure functions.

Her guide rope statement is so good, it bears repeating:

“Functional code is characterised by one thing: the absence of side effects.”

When I first read this quote, the little light bulb went on over my head and I began focusing even more on writing only pure functions.

If you think about it, this statement means exactly what I wrote at the beginning of this lesson:

Functional programming is a way of writing software applications using only pure functions and immutable values.

That’s great ... but why immutable values?

At this point you might be saying, “Okay, I buy the ‘pure functions’ portion of your definition, but what does immutable values have to do with this? Why can’t my variables be mutable, i.e., why can’t I use var?”

The best FP code is like algebra

I dig into this question in the “FP is Like Algebra” lesson, but the short answer here is this:

The best FP code is like algebra, and in algebra you never re-use variables. And not re-using variables has many benefits.

For example, in Scala/FP you write code that looks like this:

val a = f(x)
val b = g(a)
val c = h(b)

When you write simple expressions like this, both you and the compiler are free to rearrange the code. For instance, because a will always be exactly the same as f(x), you can replace a with f(x) at any point in your code.

The opposite of this is also true: a can always be replaced with f(x). Therefore, this equation:

val b = g(a)

is exactly the same as this equation:

val b = g(f(x))

Continuing along this line of thinking, because b is exactly equivalent to g(f(x)), you can also state c differently. This equation:

val c = h(b)

is exactly the same as this equation:

val c = h(g(f(x)))

From a programming perspective, knowing that you can always replace the immutable values a and b with their equivalent functions (and vice-versa) is extremely important. If a and b had been defined as var fields, I couldn’t make the substitutions that I did. That’s because with mutable variables you can’t be certain that later in your program a is still f(x), and b is still g(a). However, because the fields are immutable, you can make these algebraic substitutions.

FP code is easier to reason about

Furthermore, because a and b can never change, the code is easier to reason about.

With var fields you always have to have a background thread running in your brain, “Is a reassigned somewhere else? Keep an eye out for it.”

But with FP code you never have to think, “I wonder if a was reassigned anywhere?” That thought never comes to mind. a is the same as f(x), and that’s all there is to it, end of story. They are completely interchangeable, just like the algebra you knew in high school.

To put this another way, in algebra you never reassign variables, so it’s obvious that the third line here is a mistake:

a = f(x)
b = g(a)
a = h(y)      # d'oh -- `a` is reassigned!
c = i(a, b)

Clearly no mathematician would ever do that, and because FP code is like algebra, no FP developer would ever do that either.

Summary

In this lesson, I defined functional programming like this:

Functional programming is a way of writing software applications using only pure functions and immutable values.

I noted that higher-order functions (HOFs) are a terrific FP language feature, and also stated that recursion is a by-product of the definition of FP.

I also briefly discussed some of the benefits of immutable values (and FP in general):

  • The best FP code is like algebra
  • Pure functions and immutable values are easier to reason about
  • Without much support (yet), I stated that immutable values make parallel/concurrent programming easier

See also