클로저
- 코드의 블록이다.
일급 시민
으로써 변수, 성수 등으로 저장이 가능하며, 전달인자
로 전달이 가능하다.
- 함수는 이름이 있는 클로저이다.
{ (매개변수 목록) -> 반환타입 in
함수 구현부
}
func sumFunction(a: Int, b: Int) -> Int{
return a+b
}
var sum : (Int, Int) -> Int = {(a : Int, b : Int) -> Int in
return a+b
}
let sumResult: Int = sum(1,2)
print(sumResult)
sumResult = sumFuncion(a:b:)
print(sumResult)
함수 전달인자로서의 클로저
클로저
는 주로 함수의 전달인자
로 많이 사용된다.
- 함수 내부에서 원하는 코드블럭을 실행할 수 있다.
let add : (Int, Int) -> Int
add = { (a:Int, b:Int) -> Int in
return a+b
}
let substract : (Int, Int) -> Int
sunstract { (a:Int, b:Int) -> Int in
return a-b
}
let divide : (Int, Int ) -> Int
devide = {(Int, Int) -> Int in
return a / b
}
func calculate(a: Int, b: Int, method: (Int, Int) -> Int) -> Int {
return method(a,b)
}
var calculated : Int
calculated = calculate(a: 10, b:10, method: add)
print(calculated)
calculated = calculate(a: 10, b: 10, method: substract)
print(calculated)
calculated = calculate(a: 10, b: 10, method: divide)
print(calculted)
calculated = calculate(a: 10, b: 10, method: {(left: Int, right: Int) -> Int in result left * right
}
후행 클로저
클로저
가 함수의 마지막 전달인자
라면 마지막 매개변수 이름을 생략한 후 함수 소괄호 외부에 클로저를 구현할 수 있다.
- 또한, 클로저로 전달되는 인자가 하나라면
()
를 생략할 수도 있다.
result = calculate(a: 10, b:10){(left: Int, right: Int) -> Int in
return left * right
}
hello = printHello{print("hello")}
print(result)
반환타입 생략
calculate()
함수의 정의부에서 전달인자의 method()
함수는 반환형이 Int
이다. 따라서 만약 method()
를 클로저
로 전달한다면 반환형은 생략이 가능하다.
in
키워드는 생략할 수 없다.
result = calculate(a: 10, b: 10, method: { (left: Int, right: Int) in
return left + right
})
print(result)
result = calculate(a: 10, b: 10) { (left: Int, right: Int) in
return left + right
}
print(result)
타입 유추
- 메서드에 전달인자로 전달되는 클로저는 메소드에서 요구하는 형태로 전달해야 한다.
- 이는 전달인자로 전달한 클로저는 이미 타입을 준수하고 있다고 말할 수 있기떄문에 이를 생략할 수 있다.
result = calculate(a: 10, b: 10){(left, right) in return left + right}
단축 인자이름
클로저
의 매개변수 이름
이 굳이 불필요하다면, 단축 인자이름
을 활용할 수 있다. $0
, $1
, $2
로 표현한다.
- 이때는
in
키워드를 생략할 수 있다.
result = calculate(a: 10, b: 10, method: {
return $0 + $1
})
print(result)
result = calculate(a: 10, b: 10) {
return $0 + $1
}
print(result)
암시적 반환 표현
클로적
가 반환하는 값이 있다면 클로저의 마지막 줄의 결과값
은 암시적으로 반환값
으로 취급된다.
result = calculate(a: 10, b: 10) {
$0 + $1
}
print(result)
result = calculate(a: 10, b: 10) { $0 + $1 }
print(result)
축약 전과 후 비교
result = calculate(a: 10, b: 10, method: { (left: Int, right: Int) -> Int in
return left + right
})
result = calculate(a: 10, b: 10) { $0 + $1 }
print(result)
값 획득
- 클로저는 자신이 정의된 위치의 주변 문맥을 통해 상수나 변수를 획득할 수 있습니다.
- 값 획득을 통해 클로저는 주변 상수나 변수가 존재하지 않을 때도 해당 상수나 변수의 값을 자신 내부에서 참조하거나 변경할 수 있다.
func makeIncrementer(forIncrementer amount: Int) -> (() -> Int) {
var runningTotal = 0
func incrementer() -> Int{
runningTotal += amount
return runningTotal
}
return incrementer
}
- 이때 runningTotal과 amount 변수는 makeIncrementer 함수의 실행이 끝나도 사라지지 않는다.
- 게다가 incrementer 함수가 호출될 때마다 사용할 수 있다.
let incrementByTwo: (() -> Int) = makeIncrementer(forIncrement: 2)
let first: Int = incrementByTwo()
let second: Int = incrementByTwo()
let third: Int = incrementByTwo()
- 이때, makeIncrementer 함수를 하나 더 생성해주면, 자신만의 runningTotal 변수와 amount 변수를 갖는다.