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

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. Lazy Evaluation in Swift

    View Slide

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

    View Slide

  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:

    View Slide

  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

    View Slide

  5. When?

    View Slide

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

    View Slide

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

    View Slide

  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͕ධՁ͞ΕΔ

    View Slide

  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

    View Slide

  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 ͕࢖ΘΕ͍ͯͳ͍ͷʹධՁ͞Εͨʂ

    View Slide

  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 ͕࢖ΘΕ͍ͯͳ͍ͷʹධՁ͞Εͨʂ
    ϞολΠφΠʂ

    View Slide

  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

    View Slide

  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 ͕ධՁ͞ΕΔ

    View Slide

  14. ඞཁ࣌ͷΈධՁ͍ͨ͠ʂ
    ධՁλΠϛϯάมߋ͍ͨ͠ʂ

    View Slide

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

    View Slide

  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

    View Slide

  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Λ࢖͏ʂ

    View Slide

  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Λ࢖͏ʂ
    ؾ࣋ͪѱ͍

    View Slide

  19. @autoclosure

    View Slide

  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

    View Slide

  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
    ؾ࣋ͪྑ͘ͳͬͨʂ

    View Slide

  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

    View Slide

  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 ͕࠶ධՁ͞ΕΔʂ

    View Slide

  24. ࠶ධՁΛආ͚͍ͨʂ

    View Slide

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

    View Slide

  26. Call-by-need
    lazy property

    View Slide

  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

    View Slide

  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
    ̎ճݺ͹Ε͍ͯΔ͚ͲɼॳظԽ͸̍ճ͚ͩ
    ඞཁ࣌ͷΈධՁ͢Δ

    View Slide

  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

    View Slide

  30. Memoization
    func memoize( body: (T)->U ) -> (T)->U {
    var memo = Dictionary()
    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)
    Ωϟογϡ͞ΕͨͷͰ࠶ܭࢉ͕ෆཁ

    View Slide

  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

    View Slide

  32. ͝੩ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠

    View Slide