牛骨文教育服务平台(让学习变的简单)

Closures

Global and nested functions, as introduced in Functions, are actually special cases of closures. Closures take one of three forms:

  • Global functions are closures that have a name and do not capture any values.
  • Nested functions are closures that have a name and can capture values from their enclosing function.
  • Closure expressions are unnamed closures written in a lightweight syntax that can capture values from their surrounding context.

Closure expression syntax has the following general form:

{ (parameters) -> return type in
    statements
}
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella”]
func backwards(s1: String, s2: String) -> Bool {
    return s1 > s2
}
// 方法1
var reversed = sort(names, backwards)
// reversed is equal to ["Ewa", "Daniella", "Chris", "Barry", "Alex”]  

// 1.5
reversed = sort(names, { (s1: String, s2: String) -> Bool in return s1 > s2 } )

// 方法2
reversed = sort(names, { s1, s2 in return s1 > s2 } ) 

// 方法3
reversed = sort(names, { s1, s2 in s1 > s2 } ) // Implicit Returns from Single-Expression Closures

// 方法4
reversed = sort(names, { $0 > $1 } )  

// 方法5
reversed = sort(names, >) 

// 方法6
reversed = sort(names) { $0 > $1 } 

It is always possible to infer parameter types and return type when passing a closure to a function as an inline closure expression. As a result, you rarely need to write an inline closure in its fullest form.

func someFunctionThatTakesAClosure(closure: () -> ()) {
    // function body goes here
}

// here"s how you call this function without using a trailing closure:

someFunctionThatTakesAClosure({
    // closure"s body goes here
    })

// here"s how you call this function with a trailing closure instead:

someFunctionThatTakesAClosure() {
    // trailing closure"s body goes here
} 

If a closure expression is provided as the function’s only argument and you provide that expression as a trailing closure, you do not need to write a pair of parentheses () after the function’s name when you call the function.

let digitNames = [
    0: "Zero", 1: "One", 2: "Two",   3: "Three", 4: "Four",
    5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
]
let numbers = [16, 58, 510] 
let strings = numbers.map {
    (var number) -> String in
    var output = ""
    while number > 0 {
        output = digitNames[number % 10]! + output
        number /= 10
    }
    return output
}
// strings is inferred to be of type String[]
// its value is ["OneSix", "FiveEight", "FiveOneZero"] 
func makeIncrementor(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementor() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementor
}

let incrementByTen = makeIncrementor(forIncrement: 10)
incrementByTen()
// returns a value of 10
incrementByTen()
// returns a value of 20
incrementByTen()
// returns a value of 30

let incrementBySeven = makeIncrementor(forIncrement: 7)
incrementBySeven()
// returns a value of 7
incrementByTen()
// returns a value of 40    

let alsoIncrementByTen = incrementByTen
alsoIncrementByTen()
// returns a value of 50 

functions and closures are reference types.