10 Minutes on Functional Programming

If you spend much time engaging with Swift, you're likely to have at least heard the term functional programming. Like many Big Ideas, it's sometimes hard to get an initial view of what it involves, without disappearing too early down a technical rabbit hole. We'll try to fix that here, with a high level overview of what to think about and what to read about, in the hope of spurring the reader on to some further digging.

What does functional programming mean?

If you have learned to programme with the object orientated family of languages, which includes Swift, Objective C, Python, Ruby, C++, and many others, you'll have got used to certain ideas that you might be tempted to regard as no-brainers. Declaring a variable and being able to change it is one that springs to mind, or perhaps creating objects that can be manipulated by several functions. Pretty fundamental concepts, you'll probably agree, but it's not the only way.

Functional programming is a completely different idea, but one that has much in its favour. When we talk about programming styles that are fundamentally different from each other, we talk of programming paradigms.

This article will not make you a FP guru, or even a FP beginner, but I do hope to persuade you that it is very much in your interest to engage with the topic, and take from it some of the valuable concepts and techniques that you can apply to your own programming. Many of Swift's more advanced features make much more sense, and so can be used way more effectively, once we have understood where they come from and why they are considered worth including in the language.

Many of FP's strengths come not so much from what you can do within the genre, but what you can't. There are things that you may be accustomed to doing that simply can't be done within functional programming - and these things are often the source of common or difficult bugs. Learning to think about programming within the constraints of FP will equip you with some powerful techniques for writing code that is more reliable, easier to understand, and less likely to allow sloppy programming practices.

So what are those constraints?

Immutability

In object oriented programming, it is generally perfectly acceptable to declare a variable, and change it's value as needed:
var a = 0
// do something with a
a = a + 1
// do something with the new value of a
In functional programming, a variable cannot change its value once it has been declared. Swift has adopted the let keyword to achieve this (leaving the var meaning as one would expect):
let a = 0
// use a
let b = a + 1
// use b
We see here that if we need to set a variable to the value a + 1 we need to assign it to a new variable b. It seems a bit daft referring to b as a variable, since it cannot be varied, but nevertheless, we speak of mutable vs. immutable variables.
So when we are inspecting FP code, we can say for certain what value a variable holds.

Strict scope (aka pure functions)

Arguably the greatest strength of FP is that functions are rigidly defined in terms of what data they can access (whether reading or writing). A function takes an argument, performs some work, and returns a value. And nothing else.

A few examples will make this clearer, starting with some non-FP code:
var a = 1
func use_a() -> Int {
return a * 2
}
use_a()
This code simply accesses a variable that is declared outside of its own scope (i.e. outside of its own curly braces), and uses it to calculate a result, which it then returns. All well and good, but the output of the function is dependent on a variable, and thus might be different each time it is called.
var a = 1
func change_a() {
a = 2
}
change_a()
This code is also very simple, taking no argument, but changing the value of a variable declared outside of its own scope. This is known as a side effect. Like the code that precedes it, this example is perfectly typical of object orientated code, which relies on functions having access to variable and objects that maintain the programme's state.
The FP way is like this:
func pure_f(i: Int) -> Int {
return i + 2
}
let a = incr(i: 41)
It requires that we provide an argument at the call site, and that the function returns a value (which we would then assign to something, since that result would otherwise be lost). Note the following: That last point is critical. It makes reasoning about functional programmes very much easier. There are no if and buts, we can always see exactly what effect calling a function will have.
In mathematics, a function is something that will always produce the same value for any given input. I don't know if this is the reason for the term functional programming, but it seems to me the essence of functional programming.

Type system

This something else that Swift has adopted. Any object or primitive, and even every function, is strongly typed, meaning that there is no ambiguity (or flexibility) between, for example, number types. A double is a double, an integer is an integer, and they cannot be interchanged. That's not to say, that we can't convert between types, but it must be dome explicitly (and therefore unambiguously).

Why the constraints?

These seeming limitations are, in fact, a huge boost to safe code, and safe coding practices. Exactly how, and why, is not going to fit into this article, you're going to have to get down to some hand-on practice, as well as some further reading. How often can someone say "Trust me on this one", I wonder?

What else does FP have to offer?

Lots. A huge amount. Several of Swift's language features have been adopted from the functional paradigm:

Higher order functions

FP makes copious use of the ability to pass functions as arguments to other functions (which are then called higher order functions), and the ability of functions to return functions. Again, a few words here can't begin to do justice to the power of this technique. If you've done any JavaScript, this won't seem like such a big deal, and it seems higher order functions are on everybody's wish-list for those languages that don't support this (or support it badly, like Objective C).

Replacing loop constructs

The following features of Swift are a great way to reduce several lines of looping boilerplate to a single line of code (using, as they do, higher order functions). They are also borrowed from functional programming languages like Haskell. These tools describe what we want to do more, rather than how we want to iterate over a list (for example), and this has given rise to the term declarative programming (where object orientated programming is one case of imperative programming).

These features are a lot easier to understand and use effectively once we have seen them used in the context from which they come. Which brings us to:

Where to go from here

The small amount of material in this article hardly begins to scratch the surface of all the Good Stuff there is to be had from getting your hands dirty with a little FP. Personally, I think this is one of the biggest bangs for the buck available in programming, and everything you learn in FP you will be able to apply to Swift programming.

Learn a purely functional language

Haskell is a good place to start, being very pure indeed. Learning the basics of Haskell is something you can do in a weekend, and it's a weekend well spent.

Have fun reading about it

Here is a legendary tutorial: learnyouahaskell.com.

There is no need to become expert in functional programming to derive huge benefits from it. It's true that it's easy to get overwhelmed by the seemingly never-ending list of 'languages you just gotta learn', but I promise you from the bottom of my heart, that you will not regret some time spent getting across the functional programming paradigm.