Functional Programming - Getting Started

As, principally, an iOS developer, Swift has made for interesting times. Whilst the first code I wrote in Swift was heavily influenced by Obj-C patterns I (like many before me) quickly discovered that this was not the best way. A core part of Reactive Programming is Functional Programming, so that seems like a good place to start.

Following some best practices, and advice from others (including Apple’s WWDC sessions) I found I was moving to writing code that adhered more closely to the Functional Programming patterns. That’s not to say it was intentional, or that I was accidentally discovering Functional Programming on my own. Just that adopting it more formally is a smaller step than I was expecting.

In summary (and this is simplified) functional programming emphasises immutability and minimises state. The output of a function is dependent only on its input. An inherent requirement is that functions do not have side effects. A common description states:

[C]omputation as the evaluation of mathematical functions
- Functional programming - Wikipedia

I’ll be honest, it took me longer than it really should have for that statement to click with me. In the hope that I’m not the only one, here’s an example showing a simple mathematical function using imperative and functional approaches. We’ll evaluate the mathematical function 3 + 2 + 6 + -1:

class ImperativeNumber {
    var value: Int

   func add(value: Int) {
        self.value += value
    }

    init(value: Int) {
        self.value = value
    }
}

let imperativeThree = ImperativeNumber(value: 3)
var imperativeNumber = imperativeThree
imperativeNumber.add(value: 2)
imperativeNumber.add(value: 6)
imperativeNumber.add(value: -1)
print(imperativeNumber.value)      // 10
print(imperativeThree.value)   // 10

struct FunctionalNumber {
    let value: Int

    func add(value: Int) -> FunctionalNumber {
        return FunctionalNumber(value: self.value + value)
    }
}

let functionalThree = FunctionalNumber(value: 3)
let functionalNumber = functionalThree
    .add(value: 2)
    .add(value: 6)
    .add(value: -1)
print(functionalNumber.value)      // 10
print(functionalThree.value)   // 3

In functional programming, like the mathematical function, the value of “3” does not change because we added “2” to it. Instead, we have a new number that we can perform a new function on. If “3” did change, as in the imperative case, then anything else that used “3” in its calculations would be affected as “3” could now be “5”, or “11”, or “10”. It’s quite common to see this chaining pattern in functional programming, and reactive programming.

A note on naming. According to Swift guidelines, a function without side-effects should be a noun, and a function that has side-effects should be a verb. It’s the difference between getting an object, or performing an action on it. See also, Array.sort and Array.sorted. However, whilst some Swift types have imperative and functional equivalents, the versions which have their roots in functional programming typically only have the functional equivalent (e.g. filter, map, flatMap) regardless of if they could be implemented in an imperative fashion. If we have a purely functional type, it should not be unexpected, to use the verb form. However, when mixing functional and imperative code, it’s likely best to adhere to the guidelines:

struct ScoreBoard {
    private(set) var counter = 0

    mutating func increment() {
        counter += 1
    }

    func incremented() -> ScoreBoard {
        return ScoreBoard(counter: counter + 1)
    }
}

What functional programming means for your code is that it is safer. If an object can’t be mutated, you aren’t at risk of an object being modified by another thread whilst you read from it. It’s also easier to test when you are guaranteed the same result based on a consistent input.

Learning Reactive Programming

I started taking a look at functional programming recently, and more particularly in the context of Reactive Programming. There’s a lot to cover and remember and I’ve found writing it down helps. To that end, I’m going to try and write a few blog posts as I go in the hope of remembering this stuff and working through some ideas as I do. Hopefully, if I make any mistakes, someone can correct me. And maybe it will help someone else.