728x90
반응형
클로저
함수형 프로그래밍 패러다임을 접할 때 꼭 알아야할 개념
클로저, 제네릭, 프로토콜, 모나드 등이 결합하여 강력한 스위프트
C 언어나 Objective-C의 블록 또는 람다와 유사
클로저는 일정 기능을 하는 코드를 하나의 블록으로 모아놓은 것을 말함
→ 함수는 클로저의 한 형태이다
{ (**매개변수들**) -> **반환 타입** in
**실행 코드**
}
// 클로저 표현 간소화
let reversed1: [String] = names.sorted { (first: String, second: String) -> Bool in
return first > second
}
let reversed2: [String] = names.sorted { (first, second) -> Bool in
return first > second
}
let reversed3: [String] = names.sorted {
return $0 > $1
}
// 암시적 반환 표현
let reversed4: [String] = names.sorted { $0 > $1 }
// 연산자 함수
let reversed5: [String] = names.sorted(by: >)
- 클로저는 참조 타입이다
탈출 클로저
- 함수의 전달인자로 전달한 클로저가 함수 종료 후에 호출될 때 클로저가 함수를 탈출(Escape)한다고 표현
- 예시 : 비동기 작업
@escaping
키워드가 없는 경우 매개변수로 사용되는 클로저는 기본으로 비탈출 클로저- 탈출 클로저 내부에서 해당 타입의 프로퍼티나 메서드, 서브스크립트 등에 접근하려면
self
키워드를 명시적으로 사용해야함 (비탈출 클로저 내부에서는self
키워드는 선택사항)
withoutActuallyEscaping
- 비탈출 클로저로 전달한 클로저가 탈출 클로저인 척 해야하는 경우 (실제로는 탈출하지 않는데 다른 함수에서 탈출 클로저를 요구하는 상황)
// withoutActuallyEscaping
let numbers = [2, 4, 6, 8]
let evenNumberPredicate = { (number: Int) -> Bool in
return number % 2 == 0
}
let oddNumberPredicate = { (number: Int) -> Bool in
return number % 2 == 1
}
func hasElements(in array: [Int], match predicate: (Int) -> Bool) -> Bool {
return withoutActuallyEscaping(predicate) { escapablePredicate in
return (array.lazy.filter { escapablePredicate($0)}.isEmpty == false)
}
}
let hasEvenNumber = hasElements(in: numbers, match: evenNumberPredicate) // true
let hasOddNumber = hasElements(in: numbers, match: oddNumberPredicate) // false
자동 클로저 (@autoclosure
)
- 함수의 전달인자로 전달하는 표현을 자동으로 변환해주는 클로저 (일반 표현의 코드를 클로저 표현의 코드로 변환)
- 전달인자를 갖지 않음, 호출되었을 때 자신이 감싸고 있는 코드의 결괏값 반환
- 클로저가 호출되기 전까지 클로저 내부 코드가 동작하지 않음, 연산 지연 가능
- 비탈출 클로저임,
@esacping
키워드 사용 가능
// 클로저를 이용한 연산 지연
var customersInLine: [String] = ["aaa", "bbb", "ccc", "ddd"]
print(customersInLine.count) // 4
// 클로저를 만들어두면 클로저 내부의 코드를 미리 실행(연산)하지 않고 가지고만 있다
let customerProvider: () -> String = {
return customersInLine.removeFirst()
}
print(customersInLine.count) // 4
print("Now serving \(customerProvider())") // "Now serving aaa"
print(customersInLine.count) // 3
// ---
// 자동 클로저의 사용
func serveCustomer(_ customerProvider: @autoclosure () -> String) {
print("Now serving \(customerProvider())")
}
serveCustomer(customersInLine.removeFirst()) // "Now serving aaa"
// 예제 assert
public func assert(_ condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String = String(), file: StaticString = #file, line: UInt = #line)
// 1
assert(false, "Error Occurred!")
assert(0 < 1, "Error Occurred!")
assert(false, (statusCode == .fileNotFound) ? "File Not Found!" : "Something going wrong!")
// 2 @autoclosure 제거
assert({ false }, { "Error Occurred!" })
assert({ 0 < 1 }, { "Error Occurred!" })
assert({ false }, {(statusCode == .fileNotFound) ? "File Not Found!" : "Something going wrong!"})
반응형
'Programming > Swift' 카테고리의 다른 글
[Swift] 문법 다시보기 - 서브스크립트 (subscript) (0) | 2021.10.15 |
---|---|
[Swift] 문법 다시보기 - 맵, 필터, 리듀스 (map, filter, reduce) (0) | 2021.10.15 |
[Swift] 문법 다시보기 - 인스턴스 생명 및 소멸, 접근제어 (0) | 2021.10.13 |
[Swift] 문법 다시보기 - 메서드 (0) | 2021.10.13 |
[Swift] 문법 다시보기 - 프로퍼티 (0) | 2021.10.12 |