2019년 1월 17일 목요일

Closures

 
  Swift Programming Language Guide: Closures, 코드부분


 
/* Closures */

// - Global functions are closures that hava 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 Expressions

// The Sorted Method

let names = ["Chirs", "Alex", "Ewa", "Barry", "Daniella"]

func backward(_ s1: String, _ s2: String) -> Bool {
   return s1 > s2
}
var reversedNames = names.sorted(by: backward)

// Closure Expression Syntax

reversedNames = names.sorted(by: {(s1: String, s2: String) -> Bool in
   return s1 > s2
})

// Inferring Type From Context

reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 })

// Implicit Returns from Single-Expression Closures

reversedNames = names.sorted(by: { s1, s2 in s1 > s2 })

// Shorthand Argument Names

reversedNames = names.sorted(by: {$0 > $1 })

// Operator Methods

reversedNames = names.sorted(by: >)

// Trailing Closures

func someFunctionThatTakesAClosure(closure: () -> Void) {
   
}
someFunctionThatTakesAClosure(closure: {
   
})

someFunctionThatTakesAClosure {
   
}

reversedNames = names.sorted() { $0 > $1 }
reversedNames = names.sorted { $0 > $1 }

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{ (number) -> String in
   var number = number
   var output = ""
   repeat {
       output = digitNames[number % 10]! + output
       number /= 10
       // number = number / 10
   } while number > 0
   return output
}
print(strings)

// Capturing Values

func makeIncrementer(forIncrement amount: Int) -> () -> Int {
   var runningTotal = 0
   func incrementer() -> Int {
       runningTotal += amount
       return runningTotal
   }
   return incrementer
}

let incrementByTen = makeIncrementer(forIncrement: 10)
incrementByTen()
incrementByTen()
incrementByTen()

let incrementBySeven = makeIncrementer(forIncrement: 7)
incrementBySeven()
incrementByTen()


// Closures Are Reference Types

let alsoIncrementByTen = incrementByTen
alsoIncrementByTen()
incrementByTen()


// Escaping Closures

var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
   completionHandlers.append(completionHandler)
}

func someFunctionWithNonescapingClosure(closure: () -> Void) {
   closure()
}

class SomeClass {
   var x = 10
   func doSomething() {
       someFunctionWithEscapingClosure {
           self.x = 100
       }
       someFunctionWithNonescapingClosure {
           x = 200
       }
   }
}

let instance = SomeClass()
instance.doSomething()
print(instance.x)


completionHandlers.first?()
//completionHandlers.first!()
//completionHandlers.last?()
print(instance.x)

// Autoclosures

var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]

print(customersInLine.count)

let customerProvider = { customersInLine.remove(at: 0)}
print(customersInLine.count)

print("Now serving \(customerProvider())!")
print(customersInLine.count)

func serve(customer customerProvider: () -> String) {
   print("Now serving \(customerProvider())!")
}

serve(customer: {customersInLine.remove(at: 0)})

func serve(customer customerProvider: @autoclosure () -> String) {
   print("Now serving \(customerProvider())!")
}

serve(customer: customersInLine.remove(at: 0))

var customerProviders: [() -> String] = []
func collectCustomerProviders(_ customerProvider: @autoclosure @escaping () -> String) {
   customerProviders.append(customerProvider)
}
collectCustomerProviders(customersInLine.remove(at: 0))
collectCustomerProviders(customersInLine.remove(at: 0))

print("Collected \(customerProviders.count) closures.")

for customerProvider in customerProviders {
   print("Now serving \(customerProvider())!")
}