Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

Lazy Evaluation in Swift

nghialv
April 15, 2015

Lazy Evaluation in Swift

nghialv

April 15, 2015
Tweet

More Decks by nghialv

Other Decks in Programming

Transcript

  1. A programming language uses an evaluation strategy to determine when

    to evaluate the argument(s) of a function call (for function, also read: operation, method, or relation) and what kind of value to pass to the function. “Wikipedia” Evaluation Strategy:
  2. A programming language uses an evaluation strategy to determine when

    to evaluate the argument(s) of a function call (for function, also read: operation, method, or relation) and what kind of value to pass to the function. “Wikipedia” Evaluation Strategy: call-by-value call-by-reference
  3. Eager Evaluation func dosomething() -> Int { println("dosomething") return 1

    } func foo(x: Int, status: String) { println("foo") } foo(dosomething(), "200") output dosomething foo
  4. Eager Evaluation func dosomething() -> Int { println("dosomething") return 1

    } func foo(x: Int, status: String) { println("foo") } foo(dosomething(), "200") output dosomething foo fooؔ਺ͷ࣮ߦલʹdosomething͕ධՁ͞ΕΔ
  5. Eager Evaluation func expensiveComputation() -> Int { println("expensiveComputation") return 1

    } func foo(x: Int, status: String) { println("foo") let result = status == "200" ? x : 0 println("result: \(result)") } foo(expensiveComputation(), "404") output expensiveComputation foo result: 0
  6. Eager Evaluation func expensiveComputation() -> Int { println("expensiveComputation") return 1

    } func foo(x: Int, status: String) { println("foo") let result = status == "200" ? x : 0 println("result: \(result)") } foo(expensiveComputation(), "404") output expensiveComputation foo result: 0 x ͕࢖ΘΕ͍ͯͳ͍ͷʹධՁ͞Εͨʂ
  7. Eager Evaluation func expensiveComputation() -> Int { println("expensiveComputation") return 1

    } func foo(x: Int, status: String) { println("foo") let result = status == "200" ? x : 0 println("result: \(result)") } foo(expensiveComputation(), "404") output expensiveComputation foo result: 0 x ͕࢖ΘΕ͍ͯͳ͍ͷʹධՁ͞Εͨʂ ϞολΠφΠʂ
  8. Function Currying func dosomething() -> Int { println("dosomething") return 1

    } func foo(a: Int)(b: Int) { println("add") } let cFoo = foo(dosomething()) //cFoo(b: 10) output dosomething
  9. Function Currying func dosomething() -> Int { println("dosomething") return 1

    } func foo(a: Int)(b: Int) { println("add") } let cFoo = foo(dosomething()) //cFoo(b: 10) output dosomething ͜ͷ࣌఺ʹ a ͕ධՁ͞ΕΔ
  10. Call-by-name func expensiveComputation() -> Int { println("expensiveComputation") return 1 }

    func foo(x: () -> Int, status: String) { println("foo") let result = status == "200" ? x() : 0 println("result: \(result)") } foo({ expensiveComputation() }, "404") output foo result: 0
  11. Call-by-name func expensiveComputation() -> Int { println("expensiveComputation") return 1 }

    func foo(x: () -> Int, status: String) { println("foo") let result = status == "200" ? x() : 0 println("result: \(result)") } foo({ expensiveComputation() }, "404") output foo result: 0 ClosureΛ࢖͏ʂ
  12. Call-by-name func expensiveComputation() -> Int { println("expensiveComputation") return 1 }

    func foo(x: () -> Int, status: String) { println("foo") let result = status == "200" ? x() : 0 println("result: \(result)") } foo({ expensiveComputation() }, "404") output foo result: 0 ClosureΛ࢖͏ʂ ؾ࣋ͪѱ͍
  13. Call-by-name func expensiveComputation() -> Int { println("expensiveComputation") return 1 }

    func foo(x: @autoclosure () -> Int, status: String) { println("foo") let result = status == "200" ? x() : 0 println("result: \(result)") } foo(expensiveComputation(), "404") output foo result: 0
  14. Call-by-name func expensiveComputation() -> Int { println("expensiveComputation") return 1 }

    func foo(x: @autoclosure () -> Int, status: String) { println("foo") let result = status == "200" ? x() : 0 println("result: \(result)") } foo(expensiveComputation(), "404") output foo result: 0 ؾ࣋ͪྑ͘ͳͬͨʂ
  15. Call-by-name func expensiveComputation() -> Int { println("expensiveComputation") return 1 }

    func foo(x: @autoclosure () -> Int, status: String) { println("foo") let result = status == "200" ? x() : 0 let t1 = x() let t2 = x() println("result: \(result)") } foo(expensiveComputation(), "404") output foo expensiveComputation expensiveComputation result: 0
  16. Call-by-name func expensiveComputation() -> Int { println("expensiveComputation") return 1 }

    func foo(x: @autoclosure () -> Int, status: String) { println("foo") let result = status == "200" ? x() : 0 let t1 = x() let t2 = x() println("result: \(result)") } foo(expensiveComputation(), "404") output foo expensiveComputation expensiveComputation result: 0 x ͕࠶ධՁ͞ΕΔʂ
  17. Call-by-need class Foo { lazy var tmp: Int = {

    println("tmp init") return 1 }() } println("before init") let foo = Foo() println("after init") foo.tmp foo.tmp output before init after init tmp init
  18. Call-by-need class Foo { lazy var tmp: Int = {

    println("tmp init") return 1 }() } println("before init") let foo = Foo() println("after init") foo.tmp foo.tmp output before init after init tmp init ̎ճݺ͹Ε͍ͯΔ͚ͲɼॳظԽ͸̍ճ͚ͩ ඞཁ࣌ͷΈධՁ͢Δ
  19. Call-by-need lazy property global variable static property struct Foo {

    static var tmp: Int = { println("tmp init") return 1 }() static func log() { println("foo") } } let foo = Foo() Foo.log() println("access tmp") let x = Foo.tmp output foo access tmp tmp init
  20. Memoization func memoize<T: Hashable, U>( body: (T)->U ) -> (T)->U

    { var memo = Dictionary<T, U>() return { x in if let q = memo[x] { return q } let r = body(x) memo[x] = r return r } } Fibonacci link: WWDC2014 Advanced Swift (from page 123) Ωϟογϡ͞ΕͨͷͰ࠶ܭࢉ͕ෆཁ
  21. When • Eager evaluation • evaluated completely before the function

    is applied • Call-by-name • evaluate only when needed • evaluate each time value is accessed • Call-by-need • evaluate only when needed • cache result for repeated access