$30 off During Our Annual Pro Sale. View details »

Lazy Evaluation in Swift

Lazy Evaluation in Swift

nghialv

April 15, 2015
Tweet

More Decks by nghialv

Other Decks in Programming

Transcript

  1. Lazy Evaluation in Swift

  2. • ΪΞ • @nghialv (twitter: nghialv2607) ΞΧ΢ϯτ • 2014೥11݄ʹCyberAgentʹ৽ଔೖࣾ •

    AmebaΞϓϦνʔϜ
  3. 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:
  4. 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
  5. When?

  6. Eager evaluation Call-by-name Call-by-need

  7. Eager Evaluation func dosomething() -> Int { println("dosomething") return 1

    } func foo(x: Int, status: String) { println("foo") } foo(dosomething(), "200") output dosomething foo
  8. 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͕ධՁ͞ΕΔ
  9. 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
  10. 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 ͕࢖ΘΕ͍ͯͳ͍ͷʹධՁ͞Εͨʂ
  11. 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 ͕࢖ΘΕ͍ͯͳ͍ͷʹධՁ͞Εͨʂ ϞολΠφΠʂ
  12. 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
  13. 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 ͕ධՁ͞ΕΔ
  14. ඞཁ࣌ͷΈධՁ͍ͨ͠ʂ ධՁλΠϛϯάมߋ͍ͨ͠ʂ

  15. Call-by-name ඞཁ࣌ͷΈධՁ͍ͨ͠ʂ ධՁλΠϛϯάมߋ͍ͨ͠ʂ

  16. 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
  17. 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Λ࢖͏ʂ
  18. 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Λ࢖͏ʂ ؾ࣋ͪѱ͍
  19. @autoclosure

  20. 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
  21. 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 ؾ࣋ͪྑ͘ͳͬͨʂ
  22. 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
  23. 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 ͕࠶ධՁ͞ΕΔʂ
  24. ࠶ධՁΛආ͚͍ͨʂ

  25. Call-by-need ࠶ධՁΛආ͚͍ͨʂ

  26. Call-by-need lazy property

  27. 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
  28. 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 ̎ճݺ͹Ε͍ͯΔ͚ͲɼॳظԽ͸̍ճ͚ͩ ඞཁ࣌ͷΈධՁ͢Δ
  29. 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
  30. 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) Ωϟογϡ͞ΕͨͷͰ࠶ܭࢉ͕ෆཁ
  31. 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
  32. ͝੩ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠