์๋ ํ์ธ์, ๊ฐ์์ ๋๋ค. ์ค๋์ ํด๋ก์ ์ ๋ํด์ ๊ณต์๋ฌธ์๋ฅผ ์ ๋ฆฌํด๋ดค์ด์. ์ ๋ฆฌํด๋ ์ ๋ง ๋ชจ๋ฅด๋๊ฒ ํฌ์ฑ์ด๋ค์.. ํด๋ก์ ๋ ์ค์ํ ๋ถ๋ถ์ธ ๋งํผ ์ถํ์ ๊ฐ๊ฐ ๊ฐ๋ณ ํฌ์คํ ์ ํตํด ๋ค์ ๊ณต๋ถํด๋ณด๋๋ก ํ๊ณ , ์ค๋์ ์ผ๋จ ์ ๋ฆฌํ๊ณ ๋ชจ๋ ๊ฐ๋ ์ ๋์ ๋ด๋ค~ ์ง์๊ธใน +1 ๋งํผ ์ป์๋ค ํ๊ณ ๋์ด๊ฐ๋ณด์ฃ . ์ถํ์ escape ํด๋ก์ , ํํํด๋ก์ , autoclosure ์ ๋ํด์ ๋๋ค๋ฅธ ํฌ์คํ ์ ํ ์์ ์ ๋๋ค. ํ์ต์ ์ฆ๊ฒ๊ตฐ!
Swift Document chap.07 Closures ๋ฐ๋ก๊ฐ๊ธฐ
Closures
ํด๋ก์ ๋ ์ฝ๋์์ ์ฌ์ฉํ๊ณ ์ ๋ฌํ ์ ์๋ ๋ ๋ฆฝ๋ ๊ธฐ๋ฅ ๋ธ๋ญ์ด๋ค. ํ ์ธ์ด๋ค์์๋ lambda์ ๊ณผ ๋น์ทํ ๊ธฐ๋ฅ์ ๊ฐ์ง๋ค.
ํด๋ก์ ๋ ์์ ์ ์ ์ํ ๊ณณ์ ์ด๋ค ์์์ ๋ณ์์ ๋ํ ์ฐธ์กฐ๋ captureํ๊ณ ์ ์ฅํ ์ ์๋ค. ํด๋น ๋ณ์์ ์์๋ฅผ ์ ๊ทผ๋ค (closing over) ๋ผ๊ณ ์ด์ผ๊ธฐํ๋ค. ์ค์ํํธ๋ ์ด๋ ๊ฒ ‘capturing’์ ๋ํ ๋ชจ๋ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ฅผ ์ง์ ์ฒ๋ฆฌํ๋ค.
- note) capturing ์ ๋ํ ๊ฐ๋ ์ ์๋ capturing Values ์์ ์์ธํ๊ฒ ์ค๋ช ํ ์์ ์ด๋ค.
์ ์ญํจ์์ ์ค์ฒฉํจ์๋ Funtions(ํจ์) ๋จ์์์ ์๊ฐํ ๊ฒ์ฒ๋ผ, ํน์ํ ๊ฒฝ์ฐ์ ํด๋ก์ ์ด๋ค. ํด๋ก์ ๋ ์๋ ์ธ๊ฐ์ง ํ์ ์ค์ ํ๋๋ฅผ ์ทจํ๋ค.
- ์ ์ญํจ์๋ ‘์ด๋ฆ์ ์์ง๋ง ์ด๋ ํ ๊ฐ๋ ๋ถ์ก์ง ์๋ ํด๋ก์ ' ์ด๋ค.
- ์ค์ฒฉํจ์๋ ‘์ด๋ฆ์ด ์์ผ๋ฉฐ ์์ ์ ๋๋ฌ์ผ ํจ์์ ๊ฐ์ ๋ถ์ก์ ์ ์๋ ํด๋ก์ '์ด๋ค.
- ํด๋ก์ ํํ์์ ‘์๊ธฐ ์ฃผ์์ ๊ฐ์ ๋ถ์ก์ ์ ์๋ ๊ฐ๋ฒผ์ด ๊ตฌ๋ฌธ์ผ๋ก ์์ฑํ ์ด๋ฆ ์๋ ํด๋ก์ ' ์ด๋ค.
์ค์ํํธ์ ํด๋ก์ ํํ์์ ๊น๋ํ๊ณ , ๋ช ํํ ์คํ์ผ์ ๊ฐ์ง๊ณ , ์ผ์์ ์ธ ์ํฉ์์ ๊ฐ๊ฒฐํ๊ณ , ๋ฒ์กํ์ง ์์ ๊ตฌ๋ฌธ์ด ๋๋๋ก ์ต์ ํํ๋ค.
- ์ํฉ์ผ๋ก ๋งค๊ฐ๋ณ์์ ๋ฐํ ๊ฐ ํ์ ์ ์ถ๋ก ํจ
- ๋จ์ผ-ํํ์ ํด๋ก์ ๋ก ์์์ ์ผ๋ก ๋ฐํํจ
- ์งง๊ฒ ์ค์ธ ์ธ์ ์ด๋ฆ
- ๋ค์ ๋ธ๋ฆฐ ํด๋ก์ (trailing closure) ๊ตฌ๋ฌธ
Closure Expressions (ํด๋ก์ ํํ์)
ํด๋ก์ ํํ์์ ๊ฐ๊ฒฐํ๊ณ ์ง์ค๋ ๊ตฌ๋ฌธ์ผ๋ก ์ธ๋ผ์ธ ํด๋ก์ ๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ด๋ค. ํด๋ก์ ํํ์์ ์๋๋ฅผ ์์ง ์๊ณ ๋ ํด๋ก์ ๋ฅผ ์ค์ ํ์์ผ๋ก ์์ฑํ๋ ์ฌ๋ฌ๊ฐ์ง ๊ตฌ๋ฌธ ์ต์ ํ๋ฅผ ์ ๊ณตํ๋ค.
The Sorted Method (์ ๋ ฌ ๋ฉ์๋)
์ค์ํํธ ํ์ค๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์๋ ค์ง ํ์ ์ ๊ฐ ๋ฐฐ์ด์ ์ ๊ณตํ ์ ๋ ฌ ํด๋ก์ ์ถ๋ ฅ์ ๊ธฐ์ด๋ก ์ ๋ ฌํ๋ sorted(by: ) ๋ผ๋ ๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ค. ์ด ๋ฉ์๋๋ ์ฌ๋ฐ๋ฅด๊ฒ ์ ๋ ฌํ ์์๋ฅผ ๊ฐ์ง ์์ ๊ณผ ๋๊ฐ์ ํ์ ์ ํฌ๊ธฐ์ ์๋ก์ด ๋ฐฐ์ด์ ๋ฐํํ๋ค. sorted(by: ) ๋ฉ์๋๋ ์๋ณธ๋ฐฐ์ด์ ์์ ํ์ง๋ ์๋๋ค.
์ ๋ ฌ ๋ฉ์๋๋ ๊ฐ์ ํ ๋ฒ ์ ๋ ฌํ๊ณ ๋๋ฉด ์ฒซ๋ฒ์งธ ๊ฐ์ด ๋๋ฒ์งธ ๊ฐ ์์ ์์ด์ผ ํ๋ ์ง ๋ค์ ์์ด์ผ ํ๋์ง ์๋ ค์ฃผ๋ Bool ๊ฐ์ ๋ฐํํ๋ ํด๋ก์ ๋ฅผ ๋ฐ์๋ค์ธ๋ค. ์ ๋ ฌ ํด๋ก์ ๋ ์ฒซ ๋ฒ์งธ ๊ฐ์ด ๋ ๋ฒ์งธ ๊ฐ ์์ ์์ด์ผํ๋ฉด true๋ฅผ ๋ฐํํ๊ณ , ๊ทธ ์ธ ๊ฒฝ์ฐ์ด๋ฉด false๋ฅผ ๋ฐํํ ํ์๊ฐ ์๋ค.
์๋ ์์ ๋ String๊ฐ ๋ฐฐ์ด์ ์ ๋ ฌํ๋ฏ๋ก, ์ ๋ ฌ ํด๋ก์ ๋ (String, String) -> Bool ํ์ ์ ํจ์์ผ ํ์๊ฐ ์๋ค.
์๋ ์์ ๋ ์ฌ๋ฐ๋ฅธ ํ์ ์ธ ๋ณดํต์ ํจ์๋ฅผ ์์ฑํ๊ณ ์ด๋ฅผ sorted(by: ) ๋ฉ์๋ ์ธ์๋ก ์ ๋ฌํ๋ค.
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
func backward(_ s1: String, _ s2: String) -> Bool {
return s1 > s1
}
var reversedNames = names.sorted(by: backward)
// reversedNames ๋ ["Ewa", "Daniella", "Chris", "Barry", "Alex"] ์ ๊ฐ์
์ด๋ ๋ณธ์ง์ ์ผ๋ก ๋จ์ผ-ํํ์ ํจ์ (a > b) ๋ฅผ ์์ฑํ๊ธฐ์๋ ๋ค์ ์ข ๊ธธ๊ณ ์ง๋ฃจํ ๋ฐฉ์์ด๋ค. ์ด ์์ ์ ์ ๋ ฌ ํด๋ก์ ๋ฅผ ํด๋ก์ ํํ์ ๊ตฌ๋ฌธ ํํ์ ์ฌ์ฉํ์ฌ ‘์ธ๋ผ์ธ (inline)’ ์ผ๋ก ์์ฑํ๋ฉด ๋ ์ข์ ๊ฒ ์ด๋ค.
Closure Expression Syntax (ํด๋ก์ ํํ์ ๊ตฌ๋ฌธ)
ํด๋ก์ ํํ์ ๊ตฌ๋ฌธ์ ์ผ๋ฐ ํ์์ ์๋์ ๊ฐ๋ค.
ํด๋ก์ ํํ์ ๊ตฌ๋ฌธ์ ๋งค๊ฐ๋ณ์๋ ์ -์ถ๋ ฅ(in-out) ๋งค๊ฐ๋ณ์์ผ ์ ์์ง๋ง, ๊ธฐ๋ณธ๊ฐ์ ๊ฐ์ง ์ ์๋ค. ๊ฐ๋ณ ๋งค๊ฐ๋ณ์ ์ด๋ฆ์ ๋ถ์ด๋ฉด ๊ฐ๋ณ ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ ์ ์๋ค. ํํ๋ ๋งค๊ฐ๋ณ์ ํ์ ๊ณผ ๋ฐํํ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋ค.
์๋ ์์ ๋ ์์์ ๊ตฌํํ๋ backward() ํจ์์ ํด๋ก์ ํํ์ ๋ฒ์ ์ด๋ค.
reversedNames = names.sorted(by: { (s1: String, s2: String ) -> Bool in
return s1 > s2
})
์ด ์ธ๋ผ์ธ ํด๋ก์ ์ ๋งค๊ฐ๋ณ์ ๋ฐ ๋ฐํ ํ์ ์ ์ธ์ backward() ํจ์์ ์๋ ์ ์ธ๊ณผ ๋ชจ๋ ์ ์์ ๋๊ฐ๋ค๋ ์ ์ ๊ธฐ์ตํ์. ๋ ๊ฒฝ์ฐ ๋ชจ๋ (s1: String, s2: String) -> Bool ๋ก ์์ฑํ๋ค. ํ์ง๋ง ์ธ๋ผ์ธํด๋ก์ ํํ์์์๋ ์ค๊ดํธ ๋ฐ์ด ์๋๋ผ ์์ ๋งค๊ฐ๋ณ์์ ๋ฐํ ํ์ ์ ์์ฑํ๋ค.
ํด๋ก์ ๋ณธ๋ฌธ์ in ํค์๋๋ก ์์ํ๋ค. ์ด ํค์๋๋ ํด๋ก์ ๋งค๊ฐ๋ณ์์ ๋ฐํ ํ์ ์ ์๋ ์ข ๋ฃํ๊ณ , ํด๋ก์ ๋ณธ๋ฌธ์ ์์ํ๋ค๊ณ ์ง์ํ๋ค.
ํด๋ก์ ๋ณธ๋ฌธ์ ์์ฃผ ์งง๊ธฐ ๋๋ฌธ์ ์ฌ์ง์ด ํ์ค๋ก๋ ์์ฑ ๊ฐ๋ฅํ๋ค. ์์ ์์ ์ฒ๋ผ return ์์ ์ํฐ๋ฅผ ์น์ง ์์๋ ๋๋ค.
reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2})
Inferring Type from Context (ํ์ ์ถ๋ก ํ๊ธฐ)
์ ๋ ฌ ํด๋ก์ ๋ฅผ ๋ฉ์๋ ์ธ์๋ก ์ ๋ฌํ๊ธฐ ๋๋ฌธ์, ์ค์ํํธ๊ฐ ๋งค๊ฐ ๋ณ์ ํ์ ๊ณผ ๋ฐํ ๊ฐ ํ์ ์ ์ถ๋ก ํ ์ ์๋ค. sorted(by: ) ๋ฉ์๋๋ฅผ ๋ฌธ์์ด ๋ฐฐ์ด์์ ํธ์ถํ๊ณ ์์ผ๋ฏ๋ก, ์ธ์๋ ๋ฐ๋์ (String, String) -> Bool ์ผ ์ ๋ฐ์ ์๋ค. ์ฆ, String, Bool ๊ณผ ๊ฐ์ด ํ์ ์ ์์ฑํ ํ์๊ฐ ์๋ค๋ ๋ป์ด๋ค. ๊ฒฐ๋ก ์ ์ผ๋ก ๋ชจ๋ ํ์ ์ ์ถ๋ก ํ ์ ์๊ธฐ ๋๋ฌธ์ ๋งค๊ฐ๋ณ์ ์ด๋ฆ ์ฃผ๋ณ์ ๋ฐํ ํ์ดํ์ ๊ดํธ๋ ์๋ตํ ์ ์๋ค.
reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )
- (note)
์ํ๋ค๋ฉด ์ฌ์ ํ ํ์ ์ ๋ช ์ํ ์ ๋ ์์ผ๋ฉฐ, ์ฝ๋๋ฅผ ์ฝ์ ๋ ๋ชจํธํจ์ ํผํ ์ ์๋ค๋ฉด ์์ฑํ๋๊ฒ ์ข๊ธด ํ๋ค. ํ์ง๋ง sotred ๋ฉ์๋์ฒ๋ผ ‘์ ๋ ฌ์ด ์ผ์ด๋๋ค'๋ผ๋ ๋ชฉ์ ์ด ๋ช ํํ๋ฉฐ ๋ฌธ์์ด ์ ๋ ฌ์ ๊ฑฐ๋ค๊ณ ์๊ธฐ ๋๋ฌธ์ ํด๋ก์ ๊ฐ string ์ด๊ฒ ๊ฑฐ๋ ํ๊ณ ๊ฐ์ ํ๊ณ ์๋ตํด๋ ์์ ํ๋ค.
Implicit Returns from Single-Expression closures (๋จ์ผ-ํํ์ ํด๋ก์ ์ ์์์ ์ธ ๋ฐํ)
๋จ์ผ-ํํ์ ํด๋ก์ ๋ ์ ์ธ์์ return ํค์๋๋ฅผ ์๋ตํจ์ผ๋ก์จ ๋จ์ผ ํํ์์ ์์์ ์ผ๋ก ๋ฐํํ ์ ์์ผ๋ฉฐ, ์๋์ ์์ ์ฒ๋ผ ํํํ ์ ์๋ค.
reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )
์ฌ๊ธฐ์ sorted(by: ) ๋ฉ์๋ ์ธ์์ ํจ์ ํ์ ์ ํด๋ก์ ๊ฐ ๋ฐ๋์ Bool ๊ฐ์ ๋ฐํํจ์ ๋ช ํํ๊ฒ ํ๋ค. ํด๋ก์ ๋ณธ๋ฌธ์ด Bool ํ์ ์ ๋ฐํํ๋ ๋จ์ผ ํํ์ (s1>s2) ๋ฅผ ๋ด๊ณ ์๊ธฐ ๋๋ฌธ์ ํท๊ฐ์ผ ์ผ์ด ์์ด return ํค์๋๋ฅผ ์๋ต ๊ฐ๋ฅํ๋ค.
Shorthand Argument Names
์ค์ํํธ๋ ์ธ๋ผ์ธ ํด๋ก์ ์, ์ธ์ ๊ฐ์ $0, $1, $2, ๋ฑ๋ฑ์ ์ด๋ฆ์ผ๋ก ์ฐธ์กฐํ ์ ์๋, ์งง๊ฒ ์ค์ธ ์ธ์ ์ด๋ฆ์ ์๋ ์ ๊ณตํ๋ค.
ํด๋ก์ ํํ์ ์์์ ์งง๊ฒ ์ค์ธ ์ธ์ ์ด๋ฆ์ ์ฌ์ฉํ๋ฉด, ์ ์์์ ํด๋ก์ ์ธ์ ๋ชฉ๋ก์ ์๋ตํ ์ ์๋ค. ์งง๊ฒ ์ค์ธ ์ธ์ ์ด๋ฆ์ ํ์ ์ ์์ํ ํจ์ ํ์ ์ผ๋ก ์ถ๋ก ํ๋ฉฐ, ์งง๊ฒ ์ค์ธ ์ธ์๋ก ์ฌ์ฉํ ๊ฐ์ฅ ๋์ ์๋ ํด๋ก์ ๊ฐ ์ทจํ ์ธ์ ๊ฐ์๋ฅผ ๊ฒฐ์ ํ๋ค. in ํค์๋๋ ์๋ตํ ์ ์๋๋ฐ, ํด๋ก์ ํํ์ ์ ์ฒด๊ฐ ์์ ์ ๋ณธ๋ฌธ๋ง์ผ๋ก ์ด๋ฃจ์ด์ง๊ธฐ ๋๋ฌธ์ด๋ค.
reversedNames = names.sorted(by: { $0 > $1 } )
์ฌ๊ธฐ์, $0๊ณผ $1 ์ ํด๋ก์ ์ ์ฒซ ๋ฒ์งธ์ ๋ ๋ฒ์งธ String ์ธ์๋ฅผ ์ฐธ์กฐํ๋ค.
Operator Methods (์ฐ์ฐ์ ๋ฉ์๋)
์ค์ ๋ก๋ ์ ํด๋ก์ ํํ์์ ๋ ์งง๊ฒ ํํํ๋ ๋ฐฉ์์ด ์๋ค. String ํ์ ์ ๋ฌธ์์ด์ ํนํ๋ ์์ ๋ณด๋ค ํฐ ์ฐ์ฐ์(>) ๊ตฌํ์ผ๋ก String ํ์ ์ ๋งค๊ฐ ๋ณ์ ๋ ๊ฐ๋ฅผ ์ทจํ๊ณ , Bool ํ์ ๊ฐ์ ๋ฐํํ๋ ๋ฉ์๋๋ฅผ ์ ์ํ๋ค.
reversedNames = names.sorted(by: >)
Trailing Closures (ํํ ํด๋ก์ )
ํด๋ก์ ํํ์์ ํจ์์ ์ต์ข ์ธ์๋ก ์ ๋ฌํ ํ์๊ฐ ์๋๋ฐ, ํด๋ก์ ํํ์์ด ์์ฃผ ๊ธธ๋ค๋ฉด, ํํ ํด๋ก์ ๋ก ๋์ ์์ฑํ๋๊ฒ ์ ์ฉํ ์ ์๋ค. ํํ ํด๋ก์ ๋ ํจ์ ํธ์ถ ๊ดํธ ๋ค์ ์์ฑํ๋ ๊ฒ์ผ์ง๋ผ๋, ์ฌ์ ํ ํจ์ ์ธ์์ด๋ค. ๋ค์ ํํํด๋ก์ ๊ตฌ๋ฌธ์ ์ฌ์ฉํ ๋๋, ํจ์ ํธ์ถ์์ ์ฒซ ๋ฒ์งธ ํด๋ก์ ์ ์ธ์ ์ด๋ฆํ (argument label) ๋ฅผ ์์ฑํ์ง ์๋๋ค. ํจ์ ํธ์ถ์ ํํ ํด๋ก์ ๋ฅผ ์ฌ๋ฌ ๊ฐ ํฌํจํ ์ ์๋ค. ์๋ ์ฒซ ๋ช๋ช ์์ ๋ ํํ ํด๋ก์ ๋ฅผ ํ๋๋ง ์ฌ์ฉํ ์์์ด๋ค.
func someFunctionThatTakesAClosure(closure: () -> Void) {
// ํจ์ ๋ณธ๋ฌธ์ ์ฌ๊ธฐ์ ๋
}
// ๋ค์์ ํํ ํด๋ก์ ๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ์ด ํจ์๋ฅผ ํธ์ถํ๋ ๋ฐฉ๋ฒ์
๋๋ค:
someFunctionThatTakesAClosure(closure: {
// ํด๋ก์ ๋ณธ๋ฌธ์ ์ฌ๊ธฐ์ ๋
})
// ๋ค์์ ํํ ํด๋ก์ ๋ฅผ ๊ฐ์ง๊ณ ์ด ํจ์๋ฅผ ํธ์ถํ๋ ๋ฐฉ๋ฒ์
๋๋ค:
someFunctionThatTakesAClosure() {
// ํํ ํด๋ก์ ๋ณธ๋ฌธ์ ์ฌ๊ธฐ์ ๋
}
- ์๊น์ ์ ์์์ ๋ดค๋ closure Expression Syntax ์ ์๋ ๋ฌธ์์ด ์ ๋ ฌ ํด๋ก์ ๋ ํํ ํด๋ก์ ๋ก sorted(by: ) ๋ฉ์๋ ๊ดํธ ๋ฐ์ ์์ฑํ ์ ์๋ค.
reversedNames = names.sorted() { $0 > $1 }
- ์ถ๊ฐ๋ก ๋ ์ค์ผ ์ ์๋ค. ํจ์๋ ๋ฉ์๋์ ์ ๊ณตํ ์ ์ผํ ์ธ์๊ฐ ํด๋ก์ ํํ์์ธ๋ฐ, ๊ทธ ํํ์ ์ ํํ ํด๋ก์ ๋ก ์ ๊ณตํ๋ค๋ฉด, ํจ์๋ฅผ ํธ์ถํ ๋ ํจ์๋ ๋ฉ์๋ ์ด๋ฆ ๋ค์ () ๋ฅผ ์์ฑํ ํ์๊ฐ ์๋ค.
reversedNames = names.sorted { $0 > $1 }
ํํ ํด๋ก์ ๋ ํ ์ค๋ก ์์ฑํ๋๊ฒ ๋ถ๊ฐ๋ฅํ ์ ๋๋ก ํด๋ก์ ๊ฐ ๊ธธ ๋ ์ ์ฉํ๊ฒ ์ฌ์ฉ๋๋ค.
ํ ์๋ก, ์ค์ํํธ Array ํ์ ์๋, ํด๋ก์ ํํ์์ ๋จ์ผ ์ธ์๋ก ์ทจํ๋, map(_:) ๋ฉ์๋๊ฐ ์๋ฐ. ๋ฐฐ์ด์ ๊ฐ ํญ๋ชฉ๋ง๋ค ํด๋ก์ ๋ฅผ ํ ๋ฒ์ฉ ํธ์ถํ๋ฉฐ, ํด๋น ํญ๋ชฉ์ (๋ค๋ฅธ ํ์ ์ผ ์๋ ์๋) ๋์ฒด ๋งตํ ๊ฐ์ ๋ฐํํ๋ค. map(_:) ์ ์ ๋ฌํ ํด๋ก์ ์ ์ฝ๋๋ฅผ ์์ฑํจ์ผ๋ก์จ ๋งตํ์ ๋ณธ์ฑ๊ณผ ๋ฐํ ๊ฐ ํ์ ์ ์ง์ ํ๋ค.
์ ๊ณตํ ํด๋ก์ ๋ฅผ ๊ฐ๊ฐ์ ๋ฐฐ์ด ์์์ ์ ์ฉํ ํ, map(_:) ๋ฉ์๋๋ ์๋ก ๋งตํํ ๋ชจ๋ ๊ฐ์, ์๋ณธ ๋ฐฐ์ด์์ ์์ ์ ํด๋นํ๋ ๊ฐ๊ณผ ๋๊ฐ์ ์์๋ก, ๋ด์ ์๋ก์ด ๋ฐฐ์ด์ ๋ฐํํ๋ค.
let digitNames = [
0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four",
5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
]
let numbers = [16, 58, 510]
์ ์ฝ๋์์ ์ ์ ์ซ์์ ์์ด ๋ฒ์ ์ด๋ฆ ์ฌ์ด์ ๋งคํ์ ๋ํ ๋์ ๋๋ฆฌ๋ฅผ ์์ฑํ๋ค. ์ด์ ํด๋ก์ ํํ์์ ๋ฐฐ์ด์ map(_:) ๋ฉ์๋ ํํํด๋ก์ ๋ก ์ ๋ฌํจ์ผ๋ก์จ numbers ๋ฐฐ์ด๋ก String ๊ฐ ๋ฐฐ์ด์ ์์ฑํ ์ ์๋ค.
let strings = numbers.map { (number) -> String in
var number = number
var output = ""
repeat {
output = digitNames[number % 10]! + output
number /= 10
} while number > 0
return output
}
// strings ๋ [String] ํ์
์ธ ๊ฒ์ผ๋ก ์ถ๋ก ํจ
// ๊ทธ ๊ฐ์ ["OneSix", "FiveEight", "FiveOneZero"] ์
- ์ฝ๋ ์ค๋ช
- map ๋ฉ์๋๋ ๋ฐฐ์ด์ ๊ฐ ํญ๋ชฉ๋ง๋ค ํด๋ก์ ํํ์์ ํ ๋ฒ ์ฉ ํธ์ถํ๋ค.
- number ๋ผ๋ ํด๋ก์ ์ ์ ๋ ฅ ๋งค๊ฐ๋ณ์, ํ์ ์ ์ง์ ํ ํ์๊ฐ ์๋๋ฐ ๋งตํํ ๋ฐฐ์ด์ ๊ฐ์ผ๋ก ํ์ ์ ์ถ๋ก ํ๊ธฐ ๋๋ฌธ์ด๋ค. (number: Int) ์๋ต
- ์ด ์์ ์์๋ ํด๋ก์ ์ number ๋งค๊ฐ๋ณ์ ๊ฐ์ผ๋ก number ๊ฐ์ ์ด๊ธฐํํ๋ฏ๋ก, ํด๋ก์ ๋ณธ๋ฌธ์์ ๊ฐ์ ์์ ํ ์ ์๋ค. (ํจ์์ ๋งค๊ฐ๋ณ์๋ ํญ์ ์์์ด๋ค.)
- ํด๋ก์ ํํ์์ ๋งตํํ ์ถ๋ ฅ ๋ฐฐ์ด์ด ์ง์ ํ ํ์ ์ ์ง์ํ๋ String ์ด๋ผ๋ ๋ฐํ ํ์ ๋ ์ง์ ํ๋ค.
- ํด๋ก์ ํํ์์ ๋งค๋ฒ ํธ์ถํ ๋๋ง๋ค output ์ด๋ผ๋ ๋ฌธ์์ด์ ์ ์ํ๋ค.
- ์ด๋ ๋๋จธ์ง ์ฐ์ฐ์ (number % 10) ์ ์จ์ number ๋ง์ง๋ง ์ซ์๋ฅผ ๊ณ์ฐํ๊ณ , ์ด ์ซ์๋ก digitNames ๋์ ๋๋ฆฌ์์ ์ ์ ํ ๋ฌธ์์ด์ ์ฐพ์๋ณธ๋ค.
- ํด๋ก์ ๋ฅผ ์ฌ์ฉํ๋ฉด 0๋ณด๋ค ํฐ ์ด๋ค ์ ์์ ๋ฌธ์์ด ํํ์ด๋ ์์ฑ ๊ฐ๋ฅํ๋ค.
- digitNames ๋์ ๋๋ฆฌ์์ ๊ฐ์ ธ์จ ๋ฌธ์์ด์ output ์์ ์ถ๊ฐํ์ฌ ์ฌ์ค์ ์์น ๊ฐ์ ๋ฌธ์์ด ๋ฒ์ ์ ์ญ์์ผ๋ก ์ ์ํ๋ค. (ํํ์ nubmer % 10 ์ 16์ด๋ฉด 6, 58์ด๋ฉด 8, 510์ด๋ฉด 0์ ๋ฐํ)
- ๊ทธ๋ฐ ๋ค์, number ๋ณ์๋ฅผ 10 ์ผ๋ก ๋๋๋ค. ์ ์์ด๊ธฐ ๋๋ฌธ์ ๋๋์ ์ค์ ๊ฐ์ ์๋ผ 16์ด๋ฉด 1, 510์ด๋ฉด 51์ด ๋๋ค.
- ์ด ๊ณผ์ ์ ๋ฐ๋ณตํ๋ค๊ฐ number ๊ฐ 0์ด ๋๋ ์๊ฐ์ ํด๋ก์ ๊ฐ output๋ฌธ์์ด์ ๋ฐํํ๊ณ map(_:)๋ฉ์๋๊ฐ ์ถ๋ ฅ ๋ฐฐ์ด์ ์ด๋ฅผ ์ถ๊ฐํ๋ค.
- (note)
- digitNames ๋์ ๋๋ฆฌ์ ์ฒจ์ ์ฐ์ฐ ํธ์ถ ๋ค์ ! ๋ฅผ ๋ถ์๋ค. ์ด๋ key๊ฐ ์กด์ฌํ์ง ์์ ๊ฒฝ์ฐ ๋์ ๋๋ฆฌ ์ฐพ์๋ณด๊ธฐ๊ฐ ์คํจํ ์ ์๋ค๋ ๊ฒ์ ์ง์ํ๊ณ ์ ๋์ ๋๋ฆฌ ์ฒจ์ ์ฐ์ฐ์ด ์ต์ ๋ ๊ฐ์ ๋ฐํํ๊ธฐ ๋๋ฌธ์ด๋ค. ์ ์์ ์์๋ number % 10 ๊ฐ digitNames ๋์ ๋๋ฆฌ์ ์ ํจํ ์ฒจ์์ฐ์ฐ key ๋ผ๋ ๊ฒ์ ํญ์ ๋ณด์ฆํ๋ฏ๋ก ๋๋ํ๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ ๋ก wrapping์ ํ์ด์ฃผ์๋ค.
Capturing Values (์บก์ฒ๊ฐ)
ํด๋ก์ ๋ ์์ ์ ์ฃผ์์ ์๋ ์์์ ๋ณ์๋ฅผ ์บก์ฒํ ์ ์๋ค. ๊ทธ๋ฌ๋ฉด ์์์ ๋ณ์๋ฅผ ์ ์ํ ์์ญ์ด ๋์ด์ ์กด์ฌํ์ง ์๋ ๊ฒฝ์ฐ์๋, ํด๋ก์ ๊ฐ ํด๋น ๋ณ์์ ์์๋ฅผ ์ฐธ์กฐํ ์ ์๋ค.
์ค์ํํธ์์ ๊ฐ์ ์บก์ฒํ ์ ์๋ ๊ฐ์ฅ ๋จ์ํ ํ์์ ํด๋ก์ ๋ ์ค์ฒฉํจ์์ด๋ค. ์ค์ฒฉํจ์๋ ์๊ธฐ ๋ฐ๊นฅ์ ํจ์์ ์ด๋ค ์ธ์๋ ์บก์ฒํ ์ ์๊ณ , ๋ฐ๊นฅ ํจ์์์ ์ ์ํ ์ด๋ค ์์๋ ๋ณ์ ์ญ์๋ ์บก์ฒ ๊ฐ๋ฅํ๋ค.
- ๋ค์ ์์ ๋ incrementer๋ผ๋ ์ค์ฒฉํจ์๋ฅผ ๋ด๊ณ ์๋ makeIncrementer ํจ์์ด๋ค.
- ์ฌ๊ธฐ์ incrementer() ํจ์๋ reunningTotal ๊ณผ amount ๋ผ๋ ๊ฐ์ ์บก์ฒํ๋ค.
- ์ด ๊ฐ์ ์บก์ฒํ๊ฒ ๋๋ฉด, ํธ์ถ๋ ๋๋ง๋ค makeIncrementer ๊ฐ runningTotal ์ amount ๋งํผ ์ฆ๊ฐ์ํค๋ ํด๋ก์ ๋ก์จ incrementer ๋ฅผ ๋ฐํํจ
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
}
intercrementer ํจ์๋ง ๋ฐ๋ก๋ณด๋ฉด, ์ด๋ค ๋งค๊ฐ๋ณ์๋ ๊ฐ์ง์ง ์๋๋ค๋ ๊ฒ์ด ํน์ดํ๋ค. ์ด ํจ์๋ runningTotal ๊ณผ amount๋ฅผ ์ฐธ์กฐํ๋ค. ์ฐธ์กฐ๋ก ์บก์ฒํ๋ค๋ ๊ฒ์ makeIncrementer ํธ์ถ์ด ๋๋ฌ์ ๋๋ runningTotal, amount ๊ฐ ์ฌ๋ผ์ง์ง ์๋๋ก ๋ณด์ฅํ๊ณ , ๋ค์๋ฒ incrementer ํจ์ ํธ์ถ ์์๋ ์บก์ฒํ ๋ ๋ณ์ ๋ชจ๋ ์ฌ์ฉ ๊ฐ๋ฅํ๋๋ก ๋ณด์ฅํ๋ค.
์ค์ ์ฌ์ฉ ์์๋ ๋ค์๊ณผ ๊ฐ๋ค.
incrementer ํจ์๋ฅผ ํธ์ถํ ๋๋ง๋ค runningTotal์ ๊ฐ์ด 10 ์ฉ ์ฆ๊ฐํ๋ ๊ฒ์ ๋ณผ ์ ์๋ค. ์ฆ ๊ฐ์ด ์ฌ๋ผ์ง์ง ์๊ณ ๊ณ์ ์ ์ง๋๋ ๊ฒ์ด๋ค. ํด๋์ค์ ์ธ์คํด์ค ํ์ ์ ํด๋ก์ ๋ฅผ ํ ๋นํ๊ณ ํด๋ก์ ๊ฐ ํด๋์ค์ ์ธ์คํด์ค๋ฅผ ์ฐธ์กฐํ๋ฉด ํด๋ก์ ์ ์ธ์คํด์ค ๊ฐ์ ๊ฐ๋ ฅํ ์ฐธ์กฐ ์ฃผ๊ธฐ๊ฐ ์์ฑ๋๋ค.
let incrementByTen = makeIncrementer(forIncrement: 10)
incrementByTen()
// 10 ์ด๋ผ๋ ๊ฐ์ ๋ฐํํจ
incrementByTen()
// 20 ์ด๋ผ๋ ๊ฐ์ ๋ฐํํจ
incrementByTen()
// 30 ์ด๋ผ๋ ๊ฐ์ ๋ฐํํจ
let incrementBySeven = makeIncrementer(forIncrement: 7)
// ์์ ๋ง์ runningTotal ๋ณ์๊ฐ ์์ฑ๋๊ธฐ ๋๋ฌธ์ ๊ธฐ์กด incrementByTen์ ์ํฅ์์ฃผ์ง ์๋๋ค.
incrementalBySeven()
// 7 ์ด๋ผ๋ ๊ฐ์ ๋ฐํํจ
incrementByTen()
// 40 ์ด๋ผ๋ ๊ฐ์ ๋ฐํํจ
Closures are Reference Type (ํด๋ก์ ๋ ์ฐธ์กฐํ์ )
์ ์์ ์์ incrementByTen ๊ณผ incrementBySeven ์ ์์์ง๋ง ์ด ์์๋ฅผ ์ฐธ์กฐํ๋ ํด๋ก์ ๋ ์์ ์ด ์บก์ฒํ runningTotal ๋ณ์๋ผ๋ ์ ์ ํ์ธํ๋ค. ๊ทธ๋ฆฌ๊ณ ์คํํ ๋๋ง๋ค ์ฌ์ ํ 10์ฉ ์ฆ๊ฐํ๋ค. ์ด๋ ํจ์์ ํด๋ก์ ๊ฐ ์ฐธ์กฐํ์ ์ด๊ธฐ ๋๋ฌธ์ด๋ค!
ํจ์๋ ํด๋ก์ ๋ฅผ ์์๋ ๋ณ์์ ํ ๋นํ๊ฒ ๋๋ฉด ์์๋ ๋ณ์์ ๋ณต์ฌ๋๋ ๊ฒ์ด ์๋ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ง ์ฐธ์กฐํ๊ฒ ๋๊ณ ์ด๋ฅผ ๋ง์ฝ ๋ค๋ฅธ ์์๋ ๋ณ์์ incrementByTen์ ํ ๋นํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ์ผ์ด ์ผ์ด๋๊ฒ ๋๋ค.
let alsoIncrementByTen = incrementByTen
alsoIncrementByTen()
// 50 ์ด๋ผ๋ ๊ฐ์ ๋ฐํํจ
incrementByTen()
// 60 ์ด๋ผ๋ ๊ฐ์ ๋ฐํํจ
์ด๋ ๊ฒ ํ๊ฒ ๋๋ฉด ์ ์ฝ๋๋ ๋๊ฐ์ ํธ์ถ์ด ๋๊ฐ๋ค๋ ๊ฒ์ ๋ณด์ฌ์ค๋ค. ์ด ์ด์ ๋, ๋ ๋ค ๋์ผํ ํด๋ก์ ๋ฅผ ์ฐธ์กฐํ๊ธฐ ๋๋ฌธ์ ๋ ๋ค ์ฆ๊ฐํ๋ฉฐ ๋์ผํ ๋์ ๊ฐ์ ๋ณด์ฌ์ค๋ค.
Escaping Closures
Escaping ํด๋ก์ ๋ ํด๋ก์ ๊ฐ ํจ์์ ์ธ์๋ก ์ ๋ฌ๋์ ๋, ํจ์์ ์คํ์ด ์ข ๋ฃ๋ ํ ์คํ๋๋ ํด๋ก์ ์ด๋ค.
ํด๋ก์ ๋ ํจ์์ ๋ํ ์ธ์๋ก ํด๋ก์ ๊ฐ ์ ๋ฌ๋ ๋, ํจ์๋ฅผ escape ํ๋ค๊ณ ํ์ง๋ง, ์ฌ์ค์ ํจ์๊ฐ ๋ฐํ๋ ํ ํธ์ถ๋๋ค. ํด๋ก์ ๋ฅผ ๋งค๊ฐ๋ณ์ ์ค ํ๋๋ก ์ฌ์ฉํ๋ ํจ์๋ฅผ ์ ์ธํ๋ฉด, ๋งค๊ฐ๋ณ์ ํ์ ์์ (@escaping) ํค์๋๋ฅผ ์์ฑํด์ ํด๋ก์ ๊ฐ Escape๋ ์ ์์์ ๋ํ๋ผ ์ ์๋ค.
ํด๋ก์ ๊ฐ Escape ํ ์ ์๋ ํ ๊ฐ์ง ๋ฐฉ๋ฒ์ ํจ์ ์ธ๋ถ์ ์ ์๋ ๋ณ์์ ํด๋ก์ ๋ฅผ ์ ์ฅํ๊ณ , ์ด๋ฅผ ๋งค๊ฐ๋ณ์๋ก ์ฌ์ฉํ๋ ๊ฒ์ด๋ค.
์๋ฅผ๋ค์ด ๋น๋๊ธฐ ์์ ์ ์์ํ๋ ๋ง์ ํจ์๋ completion handler (์๋ฃ ํธ๋ค๋ฌ) ๋ก ํด๋ก์ ๋ฅผ ์ฌ์ฉํ๋ค. ํจ์๋ ์์ ์ ์์ํ ํ ๋ฐํ๋์ง๋ง ์์ ์ด ์๋ฃ๋ ๋๊น์ง ํด๋ก์ ๊ฐ ํธ์ถ๋์ง ์๋๋ค. ํด๋ก์ ๋ Escape ํด์ผ ๋์ค์ ํธ์ถ ํ ์ ์๋๋ฐ ์๋ฅผ ๋ค ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
completionHandlers.append(completionHandler)
}
์ฌ๊ธฐ์ ํด๋ก์ ๊ฐ ์คํ๋๋ ์์๋ฅผ ์ดํด๋ณด์.
- ํด๋ก์ ๊ฐ someFunctionWithEscapingClosure ํจ์์ completionHandler ์ธ์๋ก ์ ๋ฌ๋จ.
- ํด๋ก์ completionHandler ์ด ์ธ๋ถ์์ ์ ์ธ๋ Array์ ์ถ๊ฐํจ.
- someFunctionWithEscapingClosure ํจ์๊ฐ ๊ฐ์ ๋ฐํํ๊ณ ์ข ๋ฃ๋จ.
- ํด๋ก์ completionHandler๋ ์์ง ์คํ๋์ง ์์.
completionHandler ๋ ํจ์์ ์คํ์ด ์ข ๋ฃ๋๊ธฐ ์ ์ ์คํ๋์ง ์๊ธฐ ๋๋ฌธ์ escaping ํด๋ก์ , ๋ค์ ๋งํด ํจ์ ๋ฐ์์ ์คํ๋๋ ํด๋ก์ ์ด๋ค. ์ด๋ @escaping ์ ์ฌ์ฉํ์ง ์์ผ๋ฉด ์ปดํ์ผ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
self ๋ฅผ ์ฐธ์กฐํ๋ escaping ํด๋ก์ ๋ ๋ ์ ์คํ๊ฒ ์ฌ์ฉํด์ผํ๋ค. escape ํด๋ก์ ์์ self ๋ฅผ ์บก์ฒํ๋ฉด ์ค์๋ก ๊ฐ๋ ฅํ ์ฐธ์กฐ๋ฅผ ์ฝ๊ฒ ๋ง๋ค ์ ์๋ค. ๊ฐํ ์ฐธ์กฐ๋ฅผ ๋ง๋ค๊ฒ ๋๋ฉด swift์ ARC๋ก ์ธํด ๋ฉ๋ชจ๋ฆฌ ๋ญ๋น๊ฐ ๋ฐ์ํ ์ ์๋ค. ์ผ๋ฐ์ ์ผ๋ก ํด๋ก์ ๋ ๋ณธ๋ฌธ์์ ๋ณ์๋ฅผ ์ฌ์ฉํด์ ์์์ ์ผ๋ก ๋ณ์๋ฅผ ์บก์ฒํ์ง๋ง, self๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ๋ช ์์ ์ผ๋ก ์บก์ฒ๋ฅผ ํด์ผํ๋ค. ์์๋ฅผ ์ดํด๋ณด์.
someFunctionWithNonescapingClosure(closure: () -> Void) {
closure()
}
class SomeClass {
var x = 0
func doSomething() {
someFunctionWithEscapingClosure { self.x = 100 }
someFunctionWithNonescapingClosure { x = 200 }
}
}
let instance = SomeClass()
instance.doSomething()
print(instance.x)
// "200" ์ ์ธ์ํจ
completionHandlers.first?()
print(instance.x)
// "100" ์ ์ธ์ํจ
์ ์ฝ๋๋ฅผ ๋ณด๋ฉด, someFunctionWithEscapingClosure ํจ์์ ์ ๋ฌ๋ ํด๋ก์ ๋ ๋ช ์์ ์ผ๋ก self๋ฅผ ๋ํ๋๋ค. ๋ฐ๋๋ก someFunctionWithNonescapingClosure ์ ์ ๋ฌ๋ ํด๋ก์ ๋ Escape ํด๋ก์ ๊ฐ ์๋๊ธฐ ๋๋ฌธ์ ์์์ ์ผ๋ก self ๋ฅผ ์ฐธ์กฐํ ์ ์๋ค.
class SomeOtherClass {
var x = 10
func doSomething() {
someFunctionWithEscapingClosure { [self] in x = 100 }
someFunctionWithNonescapingClosure { x = 200 }
}
}
์ด ์ฝ๋๋ ํด๋ก์ ์ ์บก์ฒ ๋ชฉ๋ก์ ํฌํจํด์ self๋ฅผ ์บก์ฒํ๊ณ , ์์์ ์ผ๋ก self๋ฅผ ์ฐธ์กฐํ๋ ๋ฐฉ๋ฒ์ด๋ค. self๊ฐ ๊ตฌ์กฐ์ฒด, ์ด๊ฑฐํ์ ์ธ์คํฐ์ค์ธ ๊ฒฝ์ฐ ์ธ์ ๋ self์ ์ฐธ์กฐํ ์ ์๋ค. ํ์ง๋ง escapeํด๋ก์ ๋ ์ด๋ฌํ ๊ฐ๋ณ์ ์ธ ๊ฒ์๋ ์บก์ฒ๋ฅผ ํ ์๊ฐ ์๋ค. ๊ตฌ์กฐ์ฒด์ ์ด๊ฑฐํ์ ๊ฐ ํ์ ์ด๊ธฐ ๋๋ฌธ์ ์ด๋ฌํ ์ฐธ์กฐ๊ฐ ์ผ์ด๋ ์ ์๋ ๊ฒ์ด๋ค! (๊ตฌ์กฐ์ฒด์ ์ด๊ฑฐํ์ ๋ณ๊ฒฝ ๊ฐ๋ฅ์ฑ์ ๊ณต์ ํ๋ ๊ฒ์ ํ์ฉํ์ง ์๋๋ค.)
struct SomeStruct {
var x = 10
mutating func doSomething() {
someFunctionWithNonescapingClosure { x = 200 } // ๋จ
someFunctionWithEscapingClosure { x = 100 } // ์๋ฌ
}
}
์ฆ ์์ ๊ฐ์ด escape ํด๋ก์ ๋ฅผ ์ฌ์ฉํ์ง ์๋ ํด๋ก์ ๋ง ๊ตฌ์กฐ์ฒด์ ์ธ์คํด์ค๋ฅผ ์ฐธ์กฐํ ์ ์๋ค. someFunctionWithEscapingClosure ๋ฅผ ํธ์ถํ๋ ๊ฒ์ self๊ฐ ๋ณ๊ฒฝ ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ ์๋ฌ์ด๋ค. ์ด๋ escape ํด๋ก์ ๋ ๊ตฌ์กฐ์ฒด์ self๋ฅผ ๋ณ๊ฒฝ ๊ฐ๋ฅํ ์ฐธ์กฐ๋ก ์บก์ณํ ์์๋ค๋ ๊ท์น์ ์๋ฐํ๋ ๊ฒ์ด๋ค.
์ถ๊ฐ) escaping closure์ ๋ํด์ ์ ๋ฆฌ๊ฐ ์ ๋ ๊ธ
[Swift] Escaping ํด๋ก์ (@escaping)
Autoclosures
Autoclosure ๋ ํจ์์ ์ธ์๋ก ์ ๋ฌ๋๋ ํํ์์ ๊ฐ์ธ๊ธฐ ์ํด ์๋์ผ๋ก ์์ฑ๋๋ ํด๋ก์ ์ด๋ค. ๋งค๊ฐ๋ณ์๋ฅผ ๊ฐ์ง์ง ์์ผ๋ฉฐ ํธ์ถ๋ ๋ ๊ทธ ์์ ์๋ ํํ์์ ๊ฐ์ ๋ฐํํ๋ค. ํธ์๋ฅผ ์ํด์ AutoClosure๋ฅผ ์ฌ์ฉํ ๋๋ ๋ช ์์ ์ธ ํด๋ก์ ๋์ ์ ๊ท ํํ์์ ์์ฑํด์ ํจ์์ ๋งค๊ฐ๋ณ์๋ฅผ ๊ฐ์ธ๋ ๊ดํธ๋ฅผ ์๋ตํ ์ ์๋ค.
Autoclosure๋ฅผ ์ํํ๋ ํจ์๋ฅผ ํธ์ถํ๋ ๊ฒ์ ์ผ๋ฐ์ ์ด์ง๋ง ์ด๋ฌํ ํจ์๋ฅผ ๊ตฌํํ๋ ๊ฒ์ ์ผ๋ฐ์ ์ด์ง ์๋ค. ์๋ฅผ๋ค์ด assert(condition:message:file:line:) ํจ์๋ condition, message ๋งค๊ฐ๋ณ์๋ฅผ ์ํด Autoclosure๋ฅผ ์ฌ์ฉํ๋ค. condition ๋งค๊ฐ๋ณ์๋ ๋๋ฒ๊ทธ ๋น๋์์๋ง ์ฌ์ฉ๋๊ณ message๋งค๊ฐ๋ณ์๋ condition์ด false์ผ ๋ ์ฌ์ฉ๋๋ค.
Autoclosure๋ฅผ ์ฌ์ฉํ๋ฉด ํด๋ก์ ๋ฅผ ํธ์ถํ ๋๊น์ง ๋ด๋ถ ์ฝ๋๊ฐ ์คํ๋์ง ์๊ธฐ ๋๋ฌธ์ ์ฌ์ฉ์ด ์ง์ฐ๋๋ค. ์ด๋ ๊ฒ ์ง์ฐ๋๋ ๊ฒ์ ๊ณ์ฐ ๋น์ฉ์ด ํฌ๊ฑฐ๋ ๋ถ์์ฉ์ด ์๋ ๊ณณ์์ ์ ์ฉํ๊ฒ ์ฐ์ผ ์ ์๋ค. ์ด๋ ์ฝ๋ ์ฌ์ฉ ์์ ์ ์ ์ดํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ์์๋ฅผ ์ดํด๋ณด์.
var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
print(customersInLine.count)
// "5" ๋ฅผ ์ธ์ํจ
let customerProvider = { customersInLine.remove(at: 0) }
print(customersInLine.count)
// "5" ๋ฅผ ์ธ์ํจ
print("Now serving \\(customerProvider())!")
// "Now serving Chris!" ๋ฅผ ์ธ์ํจ
Print(customersInLine.count)
// "4" ๋ฅผ ์ธ์ํจ
์์ ๊ฐ์ ์ฝ๋์์ customersInLine ๋ฐฐ์ด์ ์๋ ํญ๋ชฉ๋ค์ customerProvider์์ ํด๋ก์ ๋ด๋ถ ์ฝ๋๋ก ์ ๊ฑฐํ์ง๋ง, ์ค์ ๋ก๋ ์ ๊ฑฐ๊ฐ ๋์ง ์๋๋ค๋ ๊ฒ์ ๋ณผ ์ ์๋ค. ์ฆ ํด๋ก์ ๊ฐ ์ค์ ๋ก ํธ์ถ๋์ง ์๋ ์ด์ ์ํ์ด ๋์ง ์๋ ๊ฒ์ด๋ค. ์ค์ ๋ก ํธ์ถ์ ํ๊ฒ ๋๋ฉด ํด๋ก์ ๋ด๋ถ ์ฝ๋๋ฅผ ์ํํด ๋ฐฐ์ด์ ํญ๋ชฉ์ด ํ๋ ์ ๊ฑฐ ๋๋ ๊ฒ์ ๋ณผ ์ ์๋ค. ๊ทธ๋ฆฌ๊ณ customerProvider ํ์ ์ string์ด ์๋๋ผ ๋งค๊ฐ๋ณ์๊ฐ ์๊ณ ๋ฌธ์์ด์ ๋ฐํํ๋ ํจ์์ธ () -> String ์ด๋ผ๋ ์ ์ ๊ธฐ์ตํ์.
// customersInLine ์ ["Alex", "Ewa", "Barry", "Daniella"] ์
func serve(customer customerProvider: () -> String) {
print("Now serving \\(customerProvider())!")
}
serve(customer: { customersInLine.remove(at: 0) })
// "Now serving Alex!" ๋ฅผ ์ธ์ํจ
์ ์ฝ๋์์ serve ํจ์๋ ๋งค๊ฐ๋ณ์๋ก ๋ช ์์ ์ผ๋ก ํด๋ก์ ๋ฅผ ๋ฐ๊ณ ๋ฐฐ์ด์ ํญ๋ชฉ์ ํ๋ ์ ๊ฑฐํ๋ฉฐ ์ ๊ฑฐ๋ ๊ฐ์ ๋ฐํ๋ฐ์ print๋ก ์ถ๋ ฅํ๋ ํจ์์ด๋ค.
// customersInLine ์ ["Ewa", "Barry", "Daniella"] ์
func serve(customer customerProvider: @autoclosure () -> String) {
print("Now serving \\(customerProvider())!")
}
serve(customer: customersInLine.remove(at: 0))
// "Now serving Ewa!" ๋ฅผ ์ธ์ํจ
์ ์ฝ๋๋ ์ด์ ์ ์ ์ธํ serve ํจ์์ @autoclosure ํค์๋๋ฅผ ์ฌ์ฉํ์ฌ autoclosure๋ฅผ ์ฌ์ฉํ ๊ฒ์ด๋ค. ์ด๋ ๊ฒ ํ๋ฉด ํด๋ก์ ๋ฅผ ํธ์ถํ ๋ ๋ง์น Stringํ์ ์ ์ฌ์ฉํ๋ ๊ฒ์ฒ๋ผ ํจ์๋ฅผ ํธ์ถํ ์ ์๋ค. @autoclosure ๋ฅผ ๋ถ์ด๊ฒ ๋๋ฉด ์ธ์๊ฐ ์๋์ผ๋ก ํด๋ก์ ๋ก ๋ณํ๋๋ค.
๋ง์ฝ autoclosure ๊ณผ escape ํด๋ก์ ๋ฅผ ๋ ๋ค ์ฌ์ฉํ๊ณ ์ถ๋ค๋ฉด ๊ทธ๊ฒ๋ ๊ฐ๋ฅํ๋ค.
// customersInLine ์ [Barry", "Daniella"] ์
var customerProviders: [() -> String] = []
func collectCustomerProviders(_ customerProvider: @autoclosure @escaping () -> String) {
customerProviders.append(customerProvider)
}
collectCustomerProviders(customersInLine.remove(at: 0))
collectCustomerProviders(customersInLine.remove(at: 0))
print("Collected \\(customerProviders.count) closures.")
// "Collected 2 closures." ๋ฅผ ์ธ์ํจ
for customerProvider in customerProviders {
print("Now serving \\(customerProvider())!")
}
// "Now serving Barry!" ๋ฅผ ์ธ์ํจ
// "Now serving Daniella!" ๋ฅผ ์ธ์ํจ
์์ ๊ฐ์ด collectCustomerProviders์ ๋งค๊ฐ๋ณ์ customerProvider๋ก ์ ๋ฌ๋ ํด๋ก์ ๋ฅผ ํธ์ถํ๋ ๋์ collectCustomerProviders ํจ์๋ ํด๋ก์ ๋ฅผ customerProviders ๋ฐฐ์ด์ ์ถ๊ฐํ๋ค. ๋ฐฐ์ด์ collectCustomerProviders ๋ฐ์์ ์ ์ธ๋์๊ธฐ ๋๋ฌธ์ ํจ์๊ฐ ๋ฐํ๋ ํ ๋ฐฐ์ด์ ํด๋ก์ ๊ฐ ์คํ๋ ์ ์๋ค. ์ฆ ๋งค๊ฐ๋ณ์ customerProvider์ ๊ฐ์ด ํจ์์ ๋ฒ์๋ฅผ ๋ฒ์ด๋ ์ ์์ด์ผ ํ๋ ๊ฒ์ด๋ค.
์ถ๊ฐ) Autoclosure์ ์ฌ์ฉ๋ฐฉ๋ฒ๊ณผ ์์์ ๋ํด์ ์ค๋ช ์ด ์ ๋ ๊ธ
์ฝ์ด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ์๋ชป๋ ๋ถ๋ถ์ด ์์ผ๋ฉด ์ธ์ ๋ ์ง ๋ง์ํด์ฃผ์ธ์. ์์ง ํด๋ก์ ์ ๋ํด์ ๋ชจ๋ ๊ฒ์ ์ดํดํ์ง ์์ ์ํฉ์ด๋ผ ํ๋ ธ์ ์ ์์ต๋๋ค ใ ใ ํด๋ก์ ๋ฅผ ์ ๋ณตํ๋ ๊ทธ๋ ๊น์ง ๊ด๋ จ ํฌ์คํ ์ ๋๊น์ง ๊ณ์๋ฉ๋๋ค ํํ