Closure
작성일
Closure
- 이름이 없다.
- func이랑 유사하다.
function
func myScore(a: Int) -> String {
return "\(a)점"
}
let score = myScore
score
를 출력해보면,
(Int) -> String
이라고 나온다. myScore에 매개변수를 넣지 않았기 때문이다. 만약에 60이라고 넣으면,
func myScore(a: Int) -> String {
return "\(a)점"
}
let score = myScore(a: 60)
score
출력해보면,
60점
이라고 나온다.
closure
let myScore2 = { (a: Int) -> String in
return "\(a)점"
}
myScore2
를 출력해보면 똑같이
(Int) -> String
라고 나온다.
축약 (생략)
let myScore2 = { (a: Int) -> String in
return "\(a)점"
}
일 경우에(return 줄이 한줄일 경우에)
let myScore2 = { (a: Int) -> String in
"\(a)점"
}
return 생략이 가능하다.
또,
let myScore3 = { (a: Int) -> String in
"\(a)점"
}
을 보면, return 줄을 보면 String타입이기 때문에,
위에(a: Int) -> String에서 String타입이라고 타입추론이 가능하다.
따라서
let myScore4 = { (a: Int) in
"\(a)점"
}
이렇게생략할 수 있다.
또 다르게
let myScore5: (Int) -> String = { a in
"\(a)점"
}
이렇게 사용 할 수 있다.
또 다른 스타일은
let myScore6: (Int) -> String = {
return "\($0)점"
}
받은 파라미터를 생략할 수 있다.(대신($인덱스)를 사용해줘야 한다.)
사용하는 느낌
- 조건 -> 특정한 글자가 포함된 것을 찾는다.
let names = ["apple", "air", "brown", "red", "orange", "blue", "candy"]
func someFind(find: String) -> [String] {
var newNames = [String]()
for name in names{
name.contains(find){
newNames.append(name)
}
}
return newNames
}
someFind(find: "a")
를 출력해보면
["apple", "air", "orange", "candy"]
가 나온다.
하지만, 만약에 “입력한 글자로 시작하는 첫 글자를 찾는다.”라는 기능을 추가시키려면,
Closure 를 사용하면 된다.
let names = ["apple", "air", "brown", "red", "orange", "blue", "candy"]
let containsSomeText: (String, String) -> Bool = {name, find in
if name.contains(find) {
return true
}
return false
}
let isStartSomeText: (String, String) -> Bool = { name, find in
if name.first?.description == find {
return true
}
return false
}
func find(findStirng: Stirng, condition: (String, String) -> Bool) -> [Stirng] {
var newNames = [String]()
for name in names {
if condition(name, findString) {
newNames.append(name)
}
}
return newNames
}
find(findStirng: "a", condition: containsSomeText)
find(findStirng: "a", condition: isStartSomeText)
위 코드를 보면, 같은 find함수지만, condition이 뭔지에 따라 로직이 바뀐다. 즉 다양한 기능을 추가할 수 있다.
.sort()는 return이 있는데
.sorted()는 return이 없다.
즉, .sort()는 값을 받아와야한다.(원본의 순서가 바뀐다.)
.sorted()는 값을 변경하지 않는다.(원본은 그대로 있다.)
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
//sort
names.sort { (lhs, rhs) -> Bool in
return lhs > rhs
}
출력하면
["Alex", "Barry", "Chris", "Daniella", "Ewa"]
으로 출력이 된다.
names.sort { (lhs, rhs) -> Bool in
return lhs > rhs
}
하지만 위 코드를 더 짧게 변경이 가능하다.
Closure를 사용해보면,
return생략가능, return타입도 생략가능, 파라미터(lhs, rhs)생략가능
단,생략하면 in도 같이 생략해야함. 생략하면 이름을 가져올수 없어서 $0, $1로 정의된 용어로 변경해서 가져와 사용할수 있다.
따라서,
names.sort{ $0 < $1 }
이런식으로 짧게 단축시킬 수 있다.
그리고
names.sort(by: { $0 < $1 } )
이거와 같지만, 받는값이 하나라서 by를 생략한 것이다.
또 다른형태로 볼수 있는데,
names.sort(by: { $0 < $1 } )
는
names.sort(by: < )
와 같다.
그 이유는 < 자체가 Closure이미 때문이다.(단, 이떄는 by를 꼭 써줘야 한다.)