클로져 (Closure)
Written by Tejayon
클로져(Closure)
-
클로져는 함수와 같이 재사용 가능한 블럭이다. 이것은 콜렉션을 다룰 때 매유 유용하다.
-
클러져는 간단하게 말하면 이름이 없는 함수이다.
-
이름이 없다면 어떻게 사용할 수 있을지 의문이 들 수 있지만 사용하는 방법은 다음과 같다.
var addNum: (Int, Int) -> Int
addNum이라는 변수는 두개의 Int값을 받아서 Int로 리턴을 한다. 이것은 정확하게 변수를 선언하는 함수와 같다. 클로져의 타입은 함수와 같다.
addNum = {(x: Int, y: Int) -> Int in return x + y }
이것은 함수의 선언과 매우 비슷해보이지만 엄밀히 보면 차이가 있다. 같은 파라미터 리스트가 있고, 반환타입이 있다는 표시(->)가 있고 리턴 타입도 있다. 하지만 클로져의 경우, element가 중괄호 안에 있고 리턴타입 뒤에 in이라는 키워드도 있다. 그리고 이것은 함수처럼 사용될 수 있다.
let result = addNum(4, 6)
여기서 result의 값은 10이 될 것이다.
-
축약 구문
-
클로져는 축약을 하는 방법이 여러가지가 있다. 첫번째로는 클로져가 하나의 리턴을 가질 경우
addNum = {(x: Int, y: Int) -> Int in x + y }
그 다음으로는 스위프트의 타입 추론을 통해서 데이터 타입을 제거할 수 있다.
addNum = {(x, y) in x + y }
그 다음으로 클로져 addNum은 이미 두개의 Int와 리턴을 Int로 받는 다고 이미 선언을 했다. 그래서 스위프트에게 유추 시킬 수 있다. 그리고 마지막으로 파라미터의 리스트를 생략할 수 있고 스위프트는 파라미터의 첫번째를 0번째 로 시작한다고 예측해서 계산을 하게 된다.
addNum = { $0 + $1 }
-
-
파라미터에 클로져가 들어간 경우
func operateNumber: (_ a: Int, _ b: Int, operation: (Int, Int) -> Int) -> Int { let result = operation(a, b) print(result) return result }
위에 함수는 operateNumber라는 이름을 가진, 그리고 파라미터가 두개의 Int와 operation이라는 이름의 파라미터를 가지는 함수를 받고 리턴 타입으로는 Int를 반환하는 함수이다.
이 함수는 클로져와 함께 사용되었다.
let addNum: {(a: Int, b: Int) - Int in return a+ b } operateNumber(5, 7, operation: addNum)
클로져는 위에서 배운대로 축약을 할 수 있다. 위에서 배운대로 축약을 해보고 하나로 합쳐보자.
operateNumber(4,6, {(a: Int, b: Int) -> Int in return a + b })
-
클로져의 캡쳐
-
클로져의 캡쳐는 감싸여진 영역 안에서 사용될 수 있다. 이것은 매우 유용하다.
func countingClosure() -> (() -> Int) { var counter = 0 let incrementCounter: () -> Int = { counter += 1 return counter } return incrementCounter }
이 함수는 파라미터가 없고 리턴이 클로져인 함수이다. 이 클로져는 파라미터가 없고 리턴은 Int를 리턴한다.
함수로부터 반환된 클로져는 내부 변수인 counter라는 것을 매번 선언을 한다. 매번 이 함수는 다른 counter라는 변수를 불러올 것이다.
let counter1 = countingClosure() let counter2 = countingClosure() counter1() // 1 counter2() // 1 counter1() // 2 counter1() // 3 counter2() // 2
여기에서 counter1과 counter2는 같은 함수를 상수로 선언되었다. 하지만 두개의 상수의 선언된 함수는 서로 다른 것이고 이것이 실행 될 때 각각 다르게 실행이 될 것이다.
-
-
Custom sorting with closure
-
클로져는 콜렉션 타입에서 유용하게 사용을 할 수 있다. 배열에 보면 sorted라는 함수가 있다. 이 함수에 대해 알아보자.
let names = ["taejune","jun","bruce","sally"] names.sorted() //["bruce","jun","sally","taejune"]
보통의 sorted 함수는 알파벳순으로 정렬을 시키는 함수이다.
하지만 클로져를 이용하면 커스텀하게 만들 수 있다.
names.sorted{ $0.character.count > $1.character.count } //["taejune","sally","jun","bruce"]
-