Closure - Basic
클로저는 func
키워드와 함수의 이름이 없는 함수입니다. 흔히들 익명함수라고 불리기도 합니다. 이들은 이름이 없기 때문에 그들 스스로 호출을 할 수 없습니다.
- 기본 클로저 문법
{ (매개변수 목록) -> 반환타입 in
실행 코드
}
함수 vs 클로저
Function
- 이름이 있다.
func
키워드가 존재한다.in
키워드가 존재하지 않는다.
Closure
- 이름이 없다.
func
키워드가 존재하지 않는다.in
키워드가 존재한다.
func giveFunc(){ ... } // function
var giveNoFunc = {() ->in ... } // closure
//call
giveFunc()
giveNoFunc()
Function to Closure
example function code
func sayHello(name : String) -> String {
return "Hello \(name)"
}
문자열을 인자로 받고 문자열을 반환하는 함수입니다. 이 함수를 클로저로 바꿔보도록 하겠습니다.
중괄호를 제거한다.
func sayHello(name : String) -> String return "Hello \(name)"
in
키워드를 함수의 본체와 반환타입 사이에 추가합니다.func sayHello(name : String) -> String in return "Hello \(name)"
func
키워드와 함수의 이름을 제거합니다.(name : String) -> String in return "Hello \(name)"
전체를 중괄호로 감쌉니다.
{(name : String) -> String in return "Hello \(name)" }
끝입니다! 이제 클로저를 변수에 할당 후 사용이 가능합니다.
var sayHello = { (name : String) -> String in
return "Hello \(name)"
}
sayHello("Dongkeon")
// Output "Hello Dongkeon"
그렇다면 생각하실겁니다! 언제 클로져를 사용하지?
클로저는 상당히 많은 곳에서 사용되며 ios개발을 하면서 절대적으로 알아야할 문법 중 하나입니다. 사용되는 예로는 completion blocks
, callbacks
고차함수
등등 많은 곳에 사용됩니다.
클로저의 문법은 가독성이 좋다는 장점이 있습니다. 이러한 장점으로 인해 여러 종류의 축약형이 존재합니다. 이러한 축약형을 하나씩 살펴보도록 하겠습니다.
return
값으로 반환되는 타입을 추측가능var sayHello = { (name : String) in return "Hello \(name)" } /* 클로저에서는 return 키워드 또한 생략해줄 수 있습니다. 마지막에 있는 값을 반환 값으로 인식합니다. */ var sayHello = { (name : String) in "Hello \(name)" }
변수의 타입을 명시해주었다면 매개변수의 타입도 생략 가능
var sayHello : (String)->String = { "Hello \($0)" } /* $ 사인을 통해 매개변수를 0 부터 순서대로 접근 할 수 있습니다. */
클로저의 기본 문법과 이의 축약 형태를 비교해보시면 확실히 축약형이 코드를 작성하기 편하고 이러한 문법을 알고있다면 가독성 또한 좋다는 것을 아실 수 있습니다.
비교
// 기본 문법
var sayHello = { (name : String) -> String in
return "Hello \(name)"
}
// 축약형
var sayHelloTwo : (String)->String = { "Hello \($0)" }
전달인자로서의 클로저
출처 : Yagom님의 블로그클로저는 주로 함수의 전달인저로 많이 사용됩니다. 함수 내부에서 원하는 코드블럭을 실행 할 수 있습니다.
let add: (Int, Int)-> Int = add = { $0 + $1 }
let substract: (Int, Int)-> Int = add = { $0 - $1 }
let divide: (Int, Int)-> Int = add = { $0 / $1 }
let multiply: (Int, Int)-> Int = add = { $0 * $1 }
func calculate(a:Int, b:Int method:(Int,Int)->Int)->Int{
return method(a,b)
}
print(calculate(a:4, b:2, method:add)) // 6
print(calculate(a:4, b:2, method:substract)) // 2
print(calculate(a:4, b:2, method:divide)) // 2
print(calculate(a:4, b:2, method:multiply)) // 8
후행 클로저
출처 : Yagom님의 블로그클로저가 함수의 마지막 전달인자이거나 전달인자가 클로저 하나뿐이라면 전달인자로 넘기지 않고 함수를 호출 후 중괄호를 통해 클로저를 구현해줌으로써 인자 전달이 가능합니다.
result = calculate(a:3, b:2) { (left:Int, right:Int) -> Int in
return left + right
}
// 이 또한 축약형으로 작성 가능합니다.
result = calculate(a:3, b:2) { $0 + $1 }
// 이 때 $0 + $1처럼 구현이 아닌 변수 add 를 넘기는 것은 불가능합니다.
이 자료를 보아도 해당 문법을 정확히 어디에 쓰이는지 감이 오지 않을 수도 있습니다. 하지만 당장 어디에 사용되는지 몰라도 다른 사람들의 코드를 볼 때
“아! 이것이 인자로 넘어가는구나!”
“아! 이것이 클로저구나!”
라며 코드를 이해하는데 도움이 됩니다. 용도는 추후의 자료를 통해 살펴보도록 하겠습니다.