Functional Swift

Geison
6 min readApr 23, 2017

Functional Programming by Wikipidia:

“Functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data”. In other words, functional programming promotes code with no side effects, no change of value in variables. It oposes to imperative programming, which emphasizes change of state”.

What this means?

  • No mutable data (no side effect).
  • No state (no implicit, hidden state).

Once assigned (value binding), a variable (a symbol) does not change its value.

All state is bad? No, hidden, implicit state is bad.

Functional programming do not eliminate state, it just make it visible and explicit (at least when programmers want it to be).

  • Functions are pure functions in the mathematical sense: their output depend only in their inputs, there is not “environment”.
  • Same result returned by functions called with the same inputs.

What are the advantages?

  • Cleaner code: “variables” are not modified once defined, so we don’t have to follow the change of state to comprehend what a function, a, method, a class, a whole project works.
  • Referential transparency: Expressions can be replaced by its values. If we call a function with the same parameters, we know for sure the output will be the same (there is no state anywhere that would change it).

There is a reason for which Einstein defined insanity as “doing the same thing over and over again and expecting different results”.

Advantages enabled by referential transparency

  • Memoization
  • Cache results for previous function calls.
  • Idempotence
  • Same results regardless how many times you call a function.
  • Modularization
  • We have no state that pervades the whole code, so we build our project with small, black boxes that we tie together, so it promotes bottom-up programming.
  • Ease of debugging
  • Functions are isolated, they only depend on their input and their output, so they are very easy to debug.
  • Parallelization
  • Functions calls are independent.
  • We can parallelize in different process/CPUs/computers/…
let result = func1(a, b) + func2(a, c)

We can execute func1 and func2 in parallel because a won’t be modified.

  • Concurrence
  1. With no shared data, concurrence gets a lot simpler:
  2. No semaphores.
  3. No monitors.
  4. No locks.
  5. No race-conditions.
  6. No dead-locks.

Swift is a multi paradigm programming language. As a Swift programmer why uses functional programming?

Swift is not a functional language but have a lot of features that enables us to applies functional principles in the development, turning our code more elegant, concise, maintainable, easier to understand and test.

Don’t Update, Create — String

Wrong

var name = “Geison”var name = name + “ Flores”

Right

let firstname = “Geison”let lastname = “Flores”let name = firstname + “ “ + lastname

Don’t Update, Create — Arrays

Wrong

var years: [Int] = [2001, 2002]years.append(2003)years.append(2004)print(years) // [2001, 2002, 2003, 2004]

Right

let years: [Int] = [2001, 2001]let allYears = years + [2003] + [2004, 2005]print(allYears) // [2001, 2002, 2003, 2004, 2005]

Don’t Update, Create — Dictionaries

Wrong

var ages = ["John": 30]ages["Mary"] = 28print(ages) // ["Mary": 28, "John": 30]

Right

let johnAges = ["John": 30]let maryAges = ["Mary": 28]func +<Key, Value> (lhs: [Key: Value], rhs: [Key: Value]) -> [Key: Value] {    var result = lhs    rhs.forEach{ result[$0] = $1 }    return result}let ages = johnAges + maryAgesprint(ages) // ["Mary": 28, "John": 30]

Immutable Objects

  • An OO pattern that was originated in FP world.
  • When changing a data structure, don’t modify in place but create a new object.
  • Name Mutating/nonmutating method pairs consistently. A mutating method will often have a nonmutating variant with similar semantics, but that returns a new value rather than updating an instance in-place.
  • When the operation is naturally described by a verb, use the verb’s imperative for the mutating method and apply the “ed” or “ing” suffix to name its nonmutating counterpart.
Table of method name convention

Higher Order Functions

Functions and methods are first-class objects in Swift, so if you want to pass a function to another function, you can just treat it as any other object.

typealias callerType = (String, String) -> String
func caller(function: callerType) -> Void {
let result = function("Hello", "David") print(result)}caller(function: { $0 + " " + $1 })

Map

let names = ["milu", "rantanplan"]let namesInUppercase = names.map { $0.uppercased() }print(namesInUppercase) //["MILU", "RANTANPLAN"]

Filter

let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]let oddNumbers = numbers.filter { $0 % 2 != 0 }print(oddNumbers) //[1, 3, 5, 9]

Reduce

let numbers = [1, 2, 3, 4, 5]let total = numbers.reduce(0, +)print(total) //15

Closure

func add_x(_ x: Int) -> ((Int) -> Int) {    func add_y(_ y: Int) -> Int {        return x + y    }    return add_y}let add_5 = add_x(5)let add_7 = add_x(7)print(add_5(10)) // result 15print(add_7(10)) // result 17print(add_x(2)(3)) // result 5

Currying and Partial Functions

Higher-order functions enable Currying, which the ability to take a function that accepts n parameters and turns it into a composition of n functions each of them take 1 parameter. A direct use of currying is the Partial Functions where if you have a function that accepts n parameters then you can generate from it one of more functions with some parameter values already filled in.

func plus(_ x: Int, _ y: Int) -> Int {    return x + y}func partialPlus(_ x: Int) -> ((Int) -> Int) {    func partial(_ y: Int) -> Int {        return plus(x, y)    }    return partial}let plus_one = partialPlus(1)print(plus_one(5)) // 6

Eager vs Lazy Evaluation

  • Eager evaluation: expressions are calculated at the moment that variables is assined, function called…
  • Lazy evaluation: delays the evaluation of the expression until it is needed.
  • Memory efficient: no memory used to store complete structures.
  • CPU efficient: no need to calculate the complete result before returning.
  • Laziness is not a requisite for FP, but it is a strategy that fits nicely on the paradigm(Haskell).

Swift have lazy properties and lazy collections.

Recursion

Looping by calling a function from within itself. When you don’t have access to mutable data, recursion is used to build up and chain data construction. This is because looping is not a functional concept, as it requires variables to be passed around to store the state of the loop at a given time.

  • Purely functional languages have no imperative for-loops, so they use recursion a lot.
  • If every recursion created an stack, it would blow up very soon.
  • Tail-call optimization (TCO) avoids creating a new stack when the last call in a recursion is the function itself.

FP in OOP?

It is possible do FP in OOP? Yes it is!

  • OOP is orthogonal to FP.
  • Well, at least in theory, because:
  • Typical OOP tends to emphasize change of state in objects.
  • Typical OOP mixes the concepts of identity and state.
  • Mixture of data and code raises both conceptual and practical problems.
  • OOP functional languages: Scala, F#, …

A Pratical Example

Exercise: “What’s the sum of the first 10 natural number whose square value is divisible by 5?”

Imperative

func main() -> Void {    var n: Int = 1    var numElements: Int = 0    var sum: Int = 0    while numElements < 10 {        if n * n % 5 == 0 {            sum += n            numElements += 1        }        n += 1    }    print(sum) //275}main()

Functional

print(    Array(1...100)        .filter({$0 * $0 % 5 == 0})        .prefix(10)        .reduce(0, +)) //275

The last advice

Learn at least one functional language, it will open your mind to a new paradigm becoming you a better programmer.

Some Functional Languages:

  • Haskell
  • ML (Standard ML, Objective Caml, …)
  • Scheme
  • Erlang
  • Scala
  • Closure
  • F#

Conclusion

  • As you can see, Swift helps you write in functional style but it doesn’t force you to it.
  • Writing in functional style enhances your code and makes it more self documented. Actually it will make it more thread-safe also.
  • The main support for FP in Swift comes from the use of closures, pattern matching, lazy evaluation and generics.
  • Any other thoughts?

Find this useful? Then click on the ❤ button below to help spread the word, and leave a comment below.

I will be glad to hear your comments and ideas about Mob Programming on the Explore Phase.

Geison Goes
Senior Consulting Engineer at
ThoughtWorks
Email
geisonfgf@gmail.com
Twiter
@geisonfgfg
Medium
@geisonfgfg

--

--

Geison

Software Craftsman, traveller, dog trainer and Husband.