스위프트 Closure

Closures are self-contained blocks of functionality that can be passed around and used in your code.

Sources from Swift Language Guide

Closure

1-1. Global function

1-2. Nested function (중첩함수)

func chooseStepFunction(backward: Bool) -> (Int) -> Int {
    func stepForward(input: Int) -> Int { return input + 1 }
    func stepBackward(input: Int) -> Int { return input - 1 }
    // backward가 트루니? true면 stepBackward, false면 stepForward
    return backward ? stepBackward : stepForward
}
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementer() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementer
}
let incrementByTen = makeIncrementer(forIncrement: 10)
incrementByTen()
// returns a value of 10
incrementByTen()
// returns a value of 20
incrementByTen()
// returns a value of 30

1-3. Closure expressions

클로저를 활용한 배열의 Method

01. Filter

filter(includeElement: (T) -> Bool) -> [T]
let bigNumbers = [2,4,20,100,30].filter({$0 > 20})
//bigNumbers = [100,30]

02. Map

map(transform: (T) -> U) -> [U]
let stringified: [String] = [1,2,3].map { String($0) }
// ["1","2","3"]

Chaining

var numbers = [1, 2, 3, 4, 5, 6]

let sum = numbers.filter {
        $0 % 2 == 1 //select all the odd numbers
    }.map {
        $0 * $0 // square them
    }.reduce(0, +) // get their sum

print(sum)

계산기 연산에 클로저 활용해보기

class CalculatorModel {
    
    // Enum Associated Value 값에 클로저 대입
    private enum OperatoinCase {
        case unary((Double) -> Double)
        // Double을 받아 Double을 리턴하는 단항 연산 함수
        case binary((Double,Double) -> Double)
        // Double, Double을 받아 Double을 리턴하는 이항 연산 함수
        case equal
    }

    
    // 딕셔너리에 클로저 Associated Value를 가진 Enum 케이스 매칭
    private var operDic: [String:OperatoinCase] = [
        "+": .binary({(num1, num2) -> Double in return num1 + num2}),
        "-": .binary({(num1, num2) -> Double in return num1 - num2}),
        "*": .binary({(num1, num2) -> Double in return num1 * num2}),
        "/": .binary({(num1, num2) -> Double in return num1 / num2}),
        "cos": .unary(cos),
        "√": .unary(sqrt),
        "±": .unary({(num1: Double) -> Double in return -num1}),
        "=": .equal
    ]

}