프로그래밍/iOS

[Swift/Ch7] 클로저: Closures

장장꾸 2023. 2. 14. 13:49
  • 이름 있는 함수를 사용하는 대신 함께 실행되는 코드 덩어리를 지칭
  • C, Objective-C의 block과 다른 프로그래밍 언어에서의 lambda와 유사한 개념

클로저의 3가지 형태

  • 전역 함수: 이름이 있고, 값을 capture하지 않는 클로저
  • 중첩 함수: 이름이 있고, 둘러싸인 함수의 값을 capture할 수 있는 클로저
  • 둘러싼 context에 따라서 값을 capture할 수 있는 이름이 없는 클로저

Swift의 클로저는 간단하고, 깔끔한 문법!

클로저 표현

Sorted 메소드 - sorted(by: )

sorted(by: ) 메소드는 주어진 배열을 정렬하여 생성한 새로운 배열을 리턴(원래 배열은 수정되지 X)

 

아래 예시는 sorted(by: )메소드가 String 배열을 알파벳 역순으로 정렬하는 예시

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
func backward(_ s1: String, _ s2: String) -> Bool {
    return s1 > s2
}
var reversedNames = names.sorted(by: backward)
// 결과는 ["Ewa", "Daniella", "Chris", "Barry", "Alex"]

sorted(by: ) 메소드는 클로저를 한 개 받음.

이 클로저는 배열의 요소를 받아서 Bool 값을 리턴함. 정렬되면 첫번째 값이 두번째 값보다 앞에 있어야할지 뒤에 있어야할지를 결정함.

즉, 이 예시에서는 정렬 클로저가 첫번째 값이 두번째 값보다 먼저 나오면 true를 리턴하고 아닌 경우 false를 리턴함.

이 예시에서 클로저는 (String, String) -> Bool 타입의 함수.

알파벳 역순이라는 것은 "B가 A보다 큰 것"을 의미함.

클로저 표현 문법

일반적인 클로저 문법은 다음과 같음

{ (<#parameters#>) -> <#return type#> in
   <#statements#>
}

튜플도 매개변수 타입, 리턴 타입으로 쓰일 수 있음.

 

위 예시를 클로저 문법을 통해서 다음과 같이 간단하게 표현 가능

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

맥락을 통해 타입 추론

Swift는 매개변수의 타입, 리턴값의 타입을 통해서 타입을 추론할 수 있음.

따라서 클로저가 함수나 메소드의 인자로 사용될 때는 완전한 형태의 인라인 클로저를 쓸 필요가 X

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

s1 > s2 자체가 Bool을 리턴한다는 의미를 내포하고 있기 때문에 return 키워드 역시 생략될 수 있음.

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

인자명 축약

Swift는 자동으로 인라인 클로저의 인자명을 줄여서 제공.

인자명을 $0, $1, $2와 같이 표현 가능.

클로저 표현이 body 전체로 이루어져 있으면 in 키워드도 생략 가능.

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

$1이 가장 큰 숫자이기 때문에클로저는 자동으로 2개의 인자를 받는다고 해석함.

연산자 메소드

클로서 표현을 더욱 축약해서 쓸 수 있음.

Swift의 String 타입은 '크다' 기호 '>'를 string-specific 구현을 정의하므로 '>' 기호만을 sorted(by: )에 전달 가능.

reversedNames = names.sorted(by: >)