2014年8月4日 星期一

Swift Language Guide - Closure

Swift Language Guide - Closure

Syntax

{ (parameters) -> return type in 
    statemetns
}
func mySort<T>(inout values: [T], compare: (T, T) -> Bool) {
    for var i = 0; i < countElements(values); i++ {
        for var j = i + 1; j < countElements(values); j++ {
            if compare(values[i], values[j]) {
                (values[i], values[j]) = (values[j], values[i])
            }
        }
    }
}

func myDump<T>(values: [T]) {
    for elm in values {
        print("\(elm) ")
    }
    println()
}

var a = [3, 2, 8, 5, 9, 7, 12, 4]

myDump(a)

mySort(&a, { (v1: Int, v2: Int) -> Bool in
        println("(\(v1), \(v2))")
        return v1 > v2

})

myDump(a)

Inferring Type From Context

func mySort<T>(inout values: [T], compare: (T, T) -> Bool) {
    for var i = 0; i < countElements(values); i++ {
        for var j = i + 1; j < countElements(values); j++ {
            if compare(values[i], values[j]) {
                (values[i], values[j]) = (values[j], values[i])
            }
        }
    }
}

func myDump<T>(values: [T]) {
    for elm in values {
        print("\(elm) ")
    }
    println()
}

var a = [3, 2, 8, 5, 9, 7, 12, 4]

myDump(a)

mySort(&a, { v1, v2 in
    println("(\(v1), \(v2))")
    return v1 > v2
})

myDump(a)

Implicit Returns from Single-Expression Closure

func mySort<T>(inout values: [T], compare: (T, T) -> Bool) {
    for var i = 0; i < countElements(values); i++ {
        for var j = i + 1; j < countElements(values); j++ {
            if compare(values[i], values[j]) {
                (values[i], values[j]) = (values[j], values[i])
            }
        }
    }
}

func myDump<T>(values: [T]) {
    for elm in values {
        print("\(elm) ")
    }
    println()
}

var a = [3, 2, 8, 5, 9, 7, 12, 4]

myDump(a)

mySort(&a, { v1, v2 in v1 > v2 } )

myDump(a)

Shorthand Argument Names

func mySort<T>(inout values: [T], compare: (T, T) -> Bool) {
    for var i = 0; i < countElements(values); i++ {
        for var j = i + 1; j < countElements(values); j++ {
            if compare(values[i], values[j]) {
                (values[i], values[j]) = (values[j], values[i])
            }
        }
    }
}

func myDump<T>(values: [T]) {
    for elm in values {
        print("\(elm) ")
    }
    println()
}

var a = [3, 2, 8, 5, 9, 7, 12, 4]

myDump(a)

mySort(&a, { $0 > $1 })

myDump(a)

Operator Functions (Extreme Shorthand)

func mySort<T>(inout values: [T], compare: (T, T) -> Bool) {
    for var i = 0; i < countElements(values); i++ {
        for var j = i + 1; j < countElements(values); j++ {
            if compare(values[i], values[j]) {
                (values[i], values[j]) = (values[j], values[i])
            }
        }
    }
}

func myDump<T>(values: [T]) {
    for elm in values {
        print("\(elm) ")
    }
    println()
}

var a = [3, 2, 8, 5, 9, 7, 12, 4]

myDump(a)

mySort(&a, >)

myDump(a)

Closure on Assignment

let a: Int = { () -> Int in
    return 10
}()

let b: Int = { (x: Int) -> Int in
    return x + 20
}(20)
println(b)

let c: Int = {
    return $0 + 20
}(20)
println(c)

let d: Int = { $0 + 20 }(20)
println(20)

Trailing Closures

The closure expression MUST be the function's FINAL argument.

func mySort<T>(inout values: [T], compare: (T, T) -> Bool) {
    for var i = 0; i < countElements(values); i++ {
        for var j = i + 1; j < countElements(values); j++ {
            if compare(values[i], values[j]) {
                (values[i], values[j]) = (values[j], values[i])
            }
        }
    }
}

func myDump<T>(values: [T]) {
    for elm in values {
        print("\(elm) ")
    }
    println()
}

var a = [3, 2, 8, 5, 9, 7, 12, 4]

myDump(a)

mySort(&a) {
    $0 > $1
}

myDump(a)

Capturing Values

var globalTotal = 0

func test(amount: Int) -> () -> (sub: Int, total: Int) {
    var subTotal = 0

    return { () -> (Int, Int) in
        globalTotal += amount
        subTotal += amount
        return (subTotal, globalTotal)
    }
}

let test10 = test(10)

var result = test10()
println("(\(result.sub), \(result.total))") <-- (10, 10)

result = test10()
println("(\(result.sub), \(result.total))") <-- (20, 20)


let test7 = test(7)
result = test7()
println("(\(result.sub), \(result.total))") <-- (7, 27)

result = test7()
println("(\(result.sub), \(result.total))") <-- (14, 34)

let testAnother10 = test(10)
result = testAnother10()
println("(\(result.sub), \(result.total))") <-- (10, 44)

Closure Are Reference Type

Assigning a closure to constans or variables is assigning its REFERENCE to them.

var globalTotal = 0

func test(amount: Int) -> () -> (sub: Int, total: Int) {
    var subTotal = 0

    return { () -> (Int, Int) in
        globalTotal += amount
        subTotal += amount
        return (subTotal, globalTotal)
    }
}

let testTen = test(10)
var rs = testTen()
println("(\(rs.sub), \(rs.total))") <-- (10, 10)

let testTenAnother = testTen            <-- Assign reference to testTenAnother
rs = testTenAnother()
println("(\(rs.sub), \(rs.total))") <-- (20, 20)
張貼留言