스위프트 공식문서를 참조하였습니다.
함수를 클로저 표현으로 만드는 방법
- func 키워드와 함수명을 지운다.
- 뒤의 { 를 앞으로 가져오고 그위치에 in을 쓴다.
func clouser(n1 : Int, n2: Int)->Int{ return n1+n2 } //이거를 클로저로 바꾸면 //1. func과 함수명 지우기 (n1: Int, n2: Int)->Int{ return n1+n2 } //2 in쓰기 {(n1: Int, n2: Int)->Int in return n1+n2} //완성!
클로저 표현
정렬 메소드
swift표준 라이브러리 에서는 sorted(by: ) 이라는 정렬 메소드를 제공하고 있다.여기에서 by 뒤에 붙어서 어떠한 방식으로 정렬할 것인지를 정의하는것을 클로저 라고 한다.
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"] func backward(_ s1: String, _ s2: String) -> Bool { return s1 > s2 } var reversedNames = names.sorted(by: backward) // reversedNames is equal to ["Ewa", "Daniella", "Chris", "Barry", "Alex"]
이러한 방식으로 함수를 통해 클로저를 만들고, 사용할수 있다.
클로저 표현 문법
{ (parameters) -> return type in statements }
클로저 문법은 다음과 같은 모양을 띄고 있다
단순한 예제를 사용해보면
var reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 })
이렇게 사용 할수 있다.
혹은 문맥에서 타입을 추론 하도록 string을 작성해주지 않아도 괜찮다.
또한 반환 키워드를 생략을 할수가 있는데
var reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )
이러한 형태또한 가능하다. 위의 형태가 타입추론, 그리고 리턴 생략 을 한 형태
최종적으로는 인자 이름또한 축약을 할수가 있는데
이때 $0,$1,$2,$3 이렇게 받는 파라미터의 순서를 통해서 statement를 작성하면 된다.
따라서
var reversedNames = names.sorted(by: { $0 > $1 } )
이렇게 간략하게 표현이 가능하다.
최종적으로 연산자 메소드를 사용해서 또 축약이 가능하다.
var reversedNames = names.sorted(by: >)
후위클로저
func someFunctionThatTakesAClosure(closure: () -> Void) { // function body goes here }
이러한 형태의 클로져가 있다면, 결국은
아까 했던 정렬 예제를 사용해본다면
var reversedNames = names.sorted(){$0>$1}
이렇게 줄일수 잇는데,
이거를 후위 클로져기 때문에 ()를 생략하고
var reversedNames =names.sorted{$0>$1}
로 작성할수 있다.
map의 예제를 보게 된다면 이렇게 사용가능.
let strings = numbers.map { (number) -> String in var number = number var output = "" repeat { output = digitNames[number % 10]! + output number /= 10 } while number > 0 return output } // let strings는 타입 추론에 의해 문자 배열([String])타입을 갖습니다. // 결과는 숫자가 문자로 바뀐 ["OneSix", "FiveEight", "FiveOneZero"]가 됩니다.
뒤에 갑캡쳐랑, 이스케이핑, 자동클로저가 있지만, 그거는 일단 생략하고
클로저의 반환값은 참조형이라는것만 알아두자.
클로저 예제
func calculater(n1: Int, n2: Int, operater: (Int,Int)->Int)->Int{ return operater(n1, n2) } func multi(no1: Int, no2: Int)->Int{ return no1 * no2 } calculater(n1: 2, n2: 3, operater: multi)
원래 이러한 코드가 있다고 했을 때
func calculater(n1: Int, n2: Int, operater: (Int,Int)->Int)->Int{ return operater(n1, n2) } calculater(n1: 2, n2: 3, operater: {(no1: Int, no2: Int)->Int in return no1 * no2 })
이런식으로 코드를 바꿀수 있다.
그리고 위에 말했듯이 첫번째 파라미터와 두번째 파라미터 순서대로 값을 받는것을 통해서 $키워드를 통해 생략해줄수 있다. 따라서 다음과 같이 정리할수 있다.
calculater(n1: 2, n2:3, operater: {$0 * $1})
여기에서 한번더 파라미터 이름을 생략할수 있게 된다.
let result = calculater(n1: 2, n2: 3){$0 * $1}
이러한 방법을 후위 클로져 라고한다.
또다른 예제
import UIKit let array = [8,2,7,4,4,2,1] func addOne(n1: Int)->Int{ return n1 + 1 } print(array.map(addOne(n1:))) print(array.map({(n1: Int)->Int in n1+1})) print(array.map(){$0+1}) print(array.map{$0+1})
이러한 순서로 클로저를 통해 코드를 간략화 할 수 있다.
클로저에 대해서
let closure: (String)-> String{ (name: String)-> String in return "개발하는 \(name)" }
가 클로저의 기본 형태이다.
이를 출력해보면
closure(name: jinyong) // 개발하는 jinyong
- 즉 클로저 그 자체는 그냥 함수라고 생각하면 된다.
- 하지만 클로저의 중요한 점은 클로저 그자체를 매개변수로 받아올수 있다는 점이다.
매개변수로서의 클로저
Uploaded by
N2T