Functional Swift

About Me

[ 
            "Name": "Michael Martinez", 
            "Current Employer": "Tinder 🔥", ​
            "Previous Employers": [ 
                "Eventbrite",  
                "Bigcommerce"
                ], 
            "Twitter": "twitter.com/mychaelmartinez", 
            "LinkedIn": "linkedin.com/in/iMichael",
            "Disclaimer": "Opinions herein do not represent my employers view"
 
] 

This isn't one of those "Object Oriented Programing is awful"  talks!

What is functional programming?

Not easy to define!

A Tentative Definition

"A paradigm of programming that requires emphasizes using pure functions and immutable data."

Other Definitions

"Functional programming is programming without assignment statements" - Robert C. Martin [0]

"Functional Programming  languages use functions as first class citizens" - Erik Meijer [1]

"In the Functional Kingdoms, Nouns and Verbs are generally considered equal-caste citizens. However, the Nouns, being, well, nouns, mostly sit around doing nothing at all. They don't see much point in running or executing anything, because the Verbs are quite active.." - Steve Yegge [3]

"Functional programming is when functions, not objects or procedures, are used as the fundamental building blocks of a program" - Ward Cunningham [2]

Characteristics

Referential Transparency

"Congress meets in the US Capital"

means the same thing as

"Congress meets in Washington D.C"

Abstract

Concrete

func incrementArray(a: [Int]) -> [Int] { 
    return a.map {$0 + 1}
}

/*
Imagine a program has "incrementArray([1,2,3])" somewhere deep in the codebase. That we can replace this function with the value "[2,3,4]" without 
changing the output of the program makes this function "Referentially Transparent"
*/

Side Effects 

Code with side effects

class Dog{ 
  var age = 0
  var ageInHumanYears = 0
  func haveBirthday() { 
    age += 1
    ageInHumanYears += 7
  } 
} 

Code without side effects

func humanBirthday(age: Int) -> Int {
  return age + 1
}

func getDogAge(ageInHumanYears: Int) -> Int {
  return ageInHumanYears * 7
}

Pure Function

  • Doesn't know about state outside its closure.
  • Doesn't change state outside its closure (side effects)
  • Always returns the same output based on its input (deterministic)

Immutable Data

Mutable Data

Immutable Data

func squareMutable(a: [Int]) -> [Int] {
  var result = [Int]()
  for i in a {
    result.append( i * i )
  }
  return result
}
func squareImmutable(a: [Int]) -> [Int] {
  return a.map {$0 * $0}  
}
let squares = squareImmutable([1,2,3])

Immutable Data Structures

let a = [1,2,3]
let d = ["age": 28]
struct Contact {
    let name: String
    let age: Int
}

Closures*

let sqr = {(n: Int) -> Int in
    return n * n
}

// ==

func sqr(n: Int) -> Int {
    return n * n
}

On Swift Functions

 

Swift Closures 

 

Lamba in Python

 

Blocks in Ruby

Anonymous Functions in Javascript 

Functions  == Named Closures

Higher Order Functions

Takes a function as an argument

func getEvens(a: [Int]) -> [Int] { 
    func isEven(i: Int) -> Bool { 
        return (i % 2 == 0) ?  true : false 
    } 
    return a.filter(isEven) 
} 

or ...

Higher Order Functions

Returns a function 

func aggregateFunctionFactory(operation: String) -> ([Int] -> Int) {
  // Slightly contrived  
  func sum(a: [Int]) -> Int { 
    return a.reduce(0) { $0 + $1 } 
  } 
  func avg(a: [Int]) -> Int { 
    return (a.reduce(0) { $0 + $1 } / a.count)
  } 
  func max(a: [Int]) -> Int { 
    return a.reduce(0) {$1 < $0 ? $0 : $1}
  } 
  switch operation { 
    case "sum": 
      return sum 
    case "avg": 
      return avg 
    case "max": 
      return max 
    default: 
     return sum
  } 
}

Higher Order Functions

Flat Map (New in Beta 3)

// Flatten a multi-dimensional array
let a = [[1,2,3],[4,5,6]]
let aFlattened = a.flatMap({$0})
// => [1,2,3,4,5,6]

Recursion

func sumOfSquares(n: Int) -> Int { 
    if n == 0 { 
        return n
    } 
    else { 
        return (sumOfSquares(n-1) + (n * n))
    } 
} 

(kinda)

Why?

Removing Minimizing State

  • Simplicity
  • Easier to reason about
  • Thread safety
  • Composability

Composability and Reuse

$ cat monday_orders.csv |awk -f,  '{print $NF }'| round_up.py | sum.py > monday_revenue.txt

Performance

(sometimes)

A new way of thinking and problem solving

Learn More

 ^ Great Book ^

SICP

Thanks!

Functional Programming in Swift

By Michael Martinez

Functional Programming in Swift

  • 1,203