- Total
꿈꾸는리버리
Closure 넌 누구냐 ! [1/3] 본문
SwiftUI로 개발을 하면서 swift의 부족을 많이 느꼈기 때문에
NC1 끝나고 MC2 본격 시작 전에 swift의 기본기를 다져야 겠다는 생각을 많이 했다.
그래서 이번 주말에 내가 뭘 놓치고 있었는지에 대해 고민한 끝에 closure 로 시작해서,, 고차함수 그리고 optional을 이번주에 공부하기로 했다..! ( 다음주에는 property 예제들로 computed property나 type property가 어디서 사용되는지를 우선 알아보고자 한다.)
적어놔야지 할 거 같아서 !! ㅋㅅㅋ ....
그래서 시작한 Closure 공부 !!!
공부하면서 map, filter 같은 거 쓸 때 $0, $1 요런 친구들을 많이 봤었어서 클로저를 진짜 너무 공부하고 싶었다..!!
만약 나와 같은 needs를 느낀다면 !! 본 포스팅이 도움이 되길 바란다....
이렇게 드래그 되어 있는 부분이 closure가 들어가는 부분이다 !
closure의 종류
우선... function도 closure라는 것 ! 알고 있었는가...?
closure의 종류에는 named closure와 unnamed closure가 있고,
그 중에 named closure를 function이라고, unnamed closure를 closure라고 통상적으로 부른다.
1) named closure ( function )
func function(A : Int, B : Int) -> Bool {
return A > B
}
let a = function(A : 2, B : 3)
2) unnamed closure ( closure )
let closure = { (A : Int, B : Int) -> Bool in
return A > B
}
let b = closure(2,3)
요론 느낌 ?? 비슷한 듯 다른데 차차 둘의 차이를 알아보기로 하자.
내가 느끼기에는 Closure은 매개변수로 사용될 때 그 특징을 좀 더 자세하게 알 수 있게 되는 거 같다.
Closure Expressions
Closure은 아래와 같은 형태로 표현을 한다.
💡 Closure expression Syntax
{ (parameters) -> return type in // --> 여기를 closure head
statements // --> 여기를 closure body
}
한 예제를 통해 Closure을 알아보기 위해서 알아보려고 한다.
예제 )
Calculate라는 함수가 있는데,
이 함수의 매개 변수에는 두개의 정수와, +, -, *, % 을 계산하는 method Closure인 (Int, Int) -> Int 가 있다.
func Calculate(left : Int, right : Int, method : (Int , Int) -> Int) -> Int {
return method(left, right)
}
우선 func !
앞서 이야기 한 대로 closure의 종류에는 named closure와 unnamed closure가 있고,
그 중에 named closure를 function이라고, unnamed closure를 closure라고 통상적으로 부른다.
method closure의 자리에 unnamed closure가 들어가는 예제를 보기에 앞서
method closure 자리에 named closure 즉, function이 들어가도록 코드를 짜보자.
아래와 같이 addAB라는 함수를 만들어서 안에 넣으면 된다.
func addAB(left : Int , right : Int) -> Int {
left + right
}
Calculate(left: 1, right: 2, method: addAB)
unnamed closure !
위에 addAB에서 드래그 한 부분을 method의 여기에 넣으면 unnamed closure가 완성이다 !
이때 위에서 알아본 Closure expression Syntax 를 주의해서 closure head와 body를 분리해 적어보자.
{ (parameters) -> return type in // --> 여기를 closure head
statements // --> 여기를 closure body
}
결과는 다음과 같다 !
Calculate(left: 1, right: 2, method: { (left : Int , right : Int) -> Int in
return left + right
})
이런식으로 종류에 따라 덧셈, 뺄셈, 곱셈, 나눗셈의 기능을 하는 Calculate 함수, 4개 만들 수 있다.
Calculate(left: 1, right: 2, method: { (left : Int , right : Int) -> Int in
return left + right
})
Calculate(left: 1, right: 2, method: { (left : Int , right : Int) -> Int in
return left - right
})
Calculate(left: 1, right: 2, method: { (left : Int , right : Int) -> Int in
return left * right
})
Calculate(left: 1, right: 2, method: { (left : Int , right : Int) -> Int in
return left % right
})
근데 해당 내용이 뭘 의미하는지 이해하기도 힘들고 너무 길다고 느껴진다.
그래서 짜란 ~ Closure를 줄여보자.
Closure을 줄이는 방법이 몇 가지 있는데 다 줄이고 나면, 요로케 코드가 줄어든다 !
훨씬 이해하기 쉬운 형태로 된... 듯 ??
이제 Closure을 줄이는 방법을 알아보자 !
Calculate(left: 1, right: 2, method: { (left : Int , right : Int) -> Int in
return left + right
})
+을 수행하는 Calculate로, 매개변수에 +을 수행하는 closure가 있다.
이제 이 3줄 짜리 Calculate 함수의 매개변수 method 클로저를 하나하나 줄여나갈 건데,
윗 코드와 차근차근 비교해가면서 살펴보면 좋을 거 같다 :)
1) Trailing Closure
💡 Trailing은 항상 오른쪽이 아니라, "마지막 부분" 라고 생각하는 게 맞다고 한다.
한국에서는 왼 -> 오른쪽으로 글씨를 써내려가기 때문에 leading이 왼쪽, trailing이 오른쪽인데,
다른 국가에서는 반대일 수 있다.
말 그대로 Trailing Closure은 "젤 오른쪽(마지막)" 파라매터가 Closure일 때 쓸 수 있다.
" 마지막" 파라매터가 Closure일 때,
Argument Label을 생략하고 파라매터 형식이 아닌 함수 뒤에 붙여 작성 "
위 함수에서 마지막 method는 Closure이기 때문에 Trailing Closure로 나타낼 수 있다.
다음과 같이 "method" (Argument Label)을 없애고, 뒤에 Closure의 형태로 붙여 쓰면 된다.
Calculate(left: 1, right: 2){ (left : Int , right : Int) -> Int in
return left + right
}
// 기존
Calculate(left: 1, right: 2, method: { (left : Int , right : Int) -> Int in
return left + right
})
2) Inferring Type From Context
// Calculate의 정의
func Calculate(left : Int, right : Int, method : (Int , Int) -> Int) -> Int{
return method(left, right)
}
이 Calculate 함수의 정의에서 method의 형태가 (Int , Int) -> Int인 Closure임을 확인 할 수 있다.
Calculate(left: 1, right: 2){ ( left , right ) in
return left + right
}
따라서 method Closure에 type을 굳이 다 적지 않더라도 문맥상에서 type이 추론이 가능하기 때문에
:Int 이런 type을 나타내는 부분이 생략 가능하다 :)
// 기존
Calculate(left: 1, right: 2, method: { (left : Int , right : Int) -> Int in
return left + right
})
3) Implicit Returns from Single-Expression Closures
딸랑 한 줄 있는 함수에서는 return을 굳이 적어주지 않더라도 그 값이 반환 된다는 것을 암묵적으로 알 수 있다.
Calculate(left: 1, right: 2){ ( left , right ) in
left + right
}
// 기존
Calculate(left: 1, right: 2, method: { (left : Int , right : Int) -> Int in
return left + right
})
4) Shorthand Argument Names
left는 첫번째 파라매터, right는 두번째 파라매터이다.
느껴지겠지만, 파라매터의 이름보다는 몇 번째 위치인지의 값을 넣으면 되는지가 더 중요하다.
따라서 left -> $0 으로, right -> $1로 표현할 수 있다.
( 하지만 경우에 따라 남겨두는 게 가독성이 더 좋은 경우가 있어서, 상황에 따라 맞게 줄이는 것이 좋다. )
Calculate(left: 1, right: 2){ $0 + $1 }
// 기존
Calculate(left: 1, right: 2, method: { (left : Int , right : Int) -> Int in
return left + right
})
이번 포스팅에서는 closure의 기본에 대해서 알아봤다.
다음 포스팅에서는 closure의 capture 개념과 closure가 reference type이라는 것을 주제로 closure와 더 친해지고자 한다.
https://docs.swift.org/swift-book/LanguageGuide/Closures.html#ID97
'오뚝이 개발자 > swift' 카테고리의 다른 글
removeLast() vs popLast() (0) | 2022.05.24 |
---|---|
[2/2] optional chaining (6) | 2022.05.14 |
[1/2] Optional unwrapping (0) | 2022.05.14 |
Closure에서의 Capture ( feat . reference type) [2/3] (4) | 2022.05.11 |
Property(1/4) - > StoredProperty (0) | 2022.04.27 |