Closures

func fibonacci(_ x: Int) -> Int {
    x <= 2 ? 1 : fibonacci(x - 1) + fibonacci(x - 2)
}

func memoize<IHashableU>(_ fun@escaping (I) -> U) -> (I) -> U {
    // item cache
    var memo = [IU]()

    // send back a new closure that does our calculation
    return { x in
        if let r = memo[x] { return r }
        let r = fun(x)
        memo[x] = r
        return r
    }
}

let memFibonacci = memoize(fibonacci)

for i in 1...2 {
    let start = Date()
    let f33 = memFibonacci(33)
    let seconds = abs(start.timeIntervalSinceNow)

    print("\(i): f33 is \(f33)")
    print("\(i): seconds33 is \(seconds)")
}
// prints:
// 1: f33 is 3524578
// 1: seconds33 is 0.009974360466003418
// 2: f33 is 3524578
// 2: seconds33 is 4.76837158203125e-07

let start = Date()
let f34 = memFibonacci(34)
let seconds = abs(start.timeIntervalSinceNow)

print("f34 is \(f34)")
print("seconds is \(seconds)")
//f34 is 5702887
//seconds is 0.016646504402160645


This memoization method works well with non-recursive functions. Because it only remembers the result of the first function call.