Potato
์•ˆ๋…•ํ•˜์„ธ์š”, ๊ฐ์žก๋‹ˆ๋‹ค?๐Ÿฅ” ^___^ ๐Ÿ˜บ github ๋ฐ”๋กœ๊ฐ€๊ธฐ ๐Ÿ‘‰๐Ÿป

Swift/Swift Documents

[Swift] ๊ณต์‹ ๋ฌธ์„œ ์ •๋ฆฌ (7) - Closures (ํด๋กœ์ €)

๊ฐ์ž ๐Ÿฅ” 2022. 2. 16. 16:09
๋ฐ˜์‘ํ˜•

์•ˆ๋…•ํ•˜์„ธ์š”, ๊ฐ์ž์ž…๋‹ˆ๋‹ค. ์˜ค๋Š˜์€ ํด๋กœ์ €์— ๋Œ€ํ•ด์„œ ๊ณต์‹๋ฌธ์„œ๋ฅผ ์ •๋ฆฌํ•ด๋ดค์–ด์š”. ์ •๋ฆฌํ•ด๋„ ์ •๋ง ๋ชจ๋ฅด๋Š”๊ฒƒ ํˆฌ์„ฑ์ด๋„ค์š”.. ํด๋กœ์ €๋Š” ์ค‘์š”ํ•œ ๋ถ€๋ถ„์ธ ๋งŒํผ ์ถ”ํ›„์— ๊ฐ๊ฐ ๊ฐœ๋ณ„ ํฌ์ŠคํŒ…์„ ํ†ตํ•ด ๋‹ค์‹œ ๊ณต๋ถ€ํ•ด๋ณด๋„๋ก ํ•˜๊ณ , ์˜ค๋Š˜์€ ์ผ๋‹จ ์ •๋ฆฌํ•˜๊ณ  ๋ชจ๋“  ๊ฐœ๋…์— ๋ˆˆ์„ ๋–ด๋‹ค~ ์ง€์‹œ๊ธใ„น +1 ๋งŒํผ ์–ป์—ˆ๋‹ค ํ•˜๊ณ  ๋„˜์–ด๊ฐ€๋ณด์ฃ . ์ถ”ํ›„์— escape ํด๋กœ์ €, ํ›„ํ–‰ํด๋กœ์ €, autoclosure ์— ๋Œ€ํ•ด์„œ ๋˜๋‹ค๋ฅธ ํฌ์ŠคํŒ…์„ ํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค. ํ•™์Šต์€ ์ฆ๊ฒ๊ตฐ!

Swift Document chap.07 Closures ๋ฐ”๋กœ๊ฐ€๊ธฐ

 

Closures — The Swift Programming Language (Swift 5.6)

Closures Closures are self-contained blocks of functionality that can be passed around and used in your code. Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages. Closures can capture and store referen

docs.swift.org

 


Closures

ํด๋กœ์ €๋Š” ์ฝ”๋“œ์—์„œ ์‚ฌ์šฉํ•˜๊ณ  ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋Š” ๋…๋ฆฝ๋œ ๊ธฐ๋Šฅ ๋ธ”๋Ÿญ์ด๋‹ค. ํƒ€ ์–ธ์–ด๋“ค์—์„œ๋Š” lambda์‹ ๊ณผ ๋น„์Šทํ•œ ๊ธฐ๋Šฅ์„ ๊ฐ€์ง„๋‹ค.

ํด๋กœ์ €๋Š” ์ž์‹ ์„ ์ •์˜ํ•œ ๊ณณ์˜ ์–ด๋–ค ์ƒ์ˆ˜์™€ ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ์ฐธ์กฐ๋“  captureํ•˜๊ณ  ์ €์žฅํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•ด๋‹น ๋ณ€์ˆ˜์™€ ์ƒ์ˆ˜๋ฅผ ์ž ๊ทผ๋‹ค (closing over) ๋ผ๊ณ  ์ด์•ผ๊ธฐํ•œ๋‹ค. ์Šค์œ„ํ”„ํŠธ๋Š” ์ด๋ ‡๊ฒŒ ‘capturing’์— ๋Œ€ํ•œ ๋ชจ๋“  ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ๋ฅผ ์ง์ ‘ ์ฒ˜๋ฆฌํ•œ๋‹ค.

  • note) capturing ์— ๋Œ€ํ•œ ๊ฐœ๋…์€ ์•„๋ž˜ capturing Values ์—์„œ ์ž์„ธํ•˜๊ฒŒ ์„ค๋ช…ํ•  ์˜ˆ์ •์ด๋‹ค.

์ „์—ญํ•จ์ˆ˜์™€ ์ค‘์ฒฉํ•จ์ˆ˜๋Š” Funtions(ํ•จ์ˆ˜) ๋‹จ์›์—์„œ ์†Œ๊ฐœํ•œ ๊ฒƒ์ฒ˜๋Ÿผ, ํŠน์ˆ˜ํ•œ ๊ฒฝ์šฐ์˜ ํด๋กœ์ €์ด๋‹ค. ํด๋กœ์ €๋Š” ์•„๋ž˜ ์„ธ๊ฐ€์ง€ ํ˜•์‹ ์ค‘์— ํ•˜๋‚˜๋ฅผ ์ทจํ•œ๋‹ค.

  1. ์ „์—ญํ•จ์ˆ˜๋Š” ‘์ด๋ฆ„์€ ์žˆ์ง€๋งŒ ์–ด๋– ํ•œ ๊ฐ’๋„ ๋ถ™์žก์ง€ ์•Š๋Š” ํด๋กœ์ €' ์ด๋‹ค.
  2. ์ค‘์ฒฉํ•จ์ˆ˜๋Š” ‘์ด๋ฆ„์ด ์žˆ์œผ๋ฉฐ ์ž์‹ ์„ ๋‘˜๋Ÿฌ์‹ผ ํ•จ์ˆ˜์˜ ๊ฐ’์„ ๋ถ™์žก์„ ์ˆ˜ ์žˆ๋Š” ํด๋กœ์ €'์ด๋‹ค.
  3. ํด๋กœ์ €ํ‘œํ˜„์‹์€ ‘์ž๊ธฐ ์ฃผ์œ„์˜ ๊ฐ’์„ ๋ถ™์žก์„ ์ˆ˜ ์žˆ๋Š” ๊ฐ€๋ฒผ์šด ๊ตฌ๋ฌธ์œผ๋กœ ์ž‘์„ฑํ•œ ์ด๋ฆ„ ์—†๋Š” ํด๋กœ์ €' ์ด๋‹ค.

์Šค์œ„ํ”„ํŠธ์˜ ํด๋กœ์ € ํ‘œํ˜„์‹์€ ๊น”๋”ํ•˜๊ณ , ๋ช…ํ™•ํ•œ ์Šคํƒ€์ผ์„ ๊ฐ€์ง€๊ณ , ์ผ์ƒ์ ์ธ ์ƒํ™ฉ์—์„œ ๊ฐ„๊ฒฐํ•˜๊ณ , ๋ฒˆ์žกํ•˜์ง€ ์•Š์€ ๊ตฌ๋ฌธ์ด ๋˜๋„๋ก ์ตœ์ ํ™”ํ•œ๋‹ค.

  • ์ƒํ™ฉ์œผ๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ๋ฐ˜ํ™˜ ๊ฐ’ ํƒ€์ž…์„ ์ถ”๋ก ํ•จ
  • ๋‹จ์ผ-ํ‘œํ˜„์‹ ํด๋กœ์ €๋กœ ์•”์‹œ์ ์œผ๋กœ ๋ฐ˜ํ™˜ํ•จ
  • ์งง๊ฒŒ ์ค„์ธ ์ธ์ž ์ด๋ฆ„
  • ๋’ค์— ๋”ธ๋ฆฐ ํด๋กœ์ € (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"] ์ž„
  • ์ฝ”๋“œ ์„ค๋ช…
    1. map ๋ฉ”์„œ๋“œ๋Š” ๋ฐฐ์—ด์˜ ๊ฐ ํ•ญ๋ชฉ๋งˆ๋‹ค ํด๋กœ์ € ํ‘œํ˜„์‹์„ ํ•œ ๋ฒˆ ์”ฉ ํ˜ธ์ถœํ•œ๋‹ค.
    2. number ๋ผ๋Š” ํด๋กœ์ €์˜ ์ž…๋ ฅ ๋งค๊ฐœ๋ณ€์ˆ˜, ํƒ€์ž…์€ ์ง€์ •ํ•  ํ•„์š”๊ฐ€ ์—†๋Š”๋ฐ ๋งตํ•‘ํ•  ๋ฐฐ์—ด์˜ ๊ฐ’์œผ๋กœ ํƒ€์ž…์„ ์ถ”๋ก ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. (number: Int) ์ƒ๋žต
    3. ์ด ์˜ˆ์ œ์—์„œ๋Š” ํด๋กœ์ €์˜ number ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’์œผ๋กœ number ๊ฐ’์„ ์ดˆ๊ธฐํ™”ํ•˜๋ฏ€๋กœ, ํด๋กœ์ € ๋ณธ๋ฌธ์—์„œ ๊ฐ’์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. (ํ•จ์ˆ˜์™€ ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ํ•ญ์ƒ ์ƒ์ˆ˜์ด๋‹ค.)
    4. ํด๋กœ์ € ํ‘œํ˜„์‹์€ ๋งตํ•‘ํ•œ ์ถœ๋ ฅ ๋ฐฐ์—ด์ด ์ง€์ •ํ•  ํƒ€์ž…์„ ์ง€์‹œํ•˜๋Š” String ์ด๋ผ๋Š” ๋ฐ˜ํ™˜ ํƒ€์ž…๋„ ์ง€์ •ํ•œ๋‹ค.
    5. ํด๋กœ์ € ํ‘œํ˜„์‹์„ ๋งค๋ฒˆ ํ˜ธ์ถœํ•  ๋•Œ๋งˆ๋‹ค output ์ด๋ผ๋Š” ๋ฌธ์ž์—ด์„ ์ œ์ž‘ํ•œ๋‹ค.
    6. ์ด๋Š” ๋‚˜๋จธ์ง€ ์—ฐ์‚ฐ์ž (number % 10) ์„ ์จ์„œ number ๋งˆ์ง€๋ง‰ ์ˆซ์ž๋ฅผ ๊ณ„์‚ฐํ•˜๊ณ , ์ด ์ˆซ์ž๋กœ digitNames ๋”•์…”๋„ˆ๋ฆฌ์—์„œ ์ ์ ˆํ•œ ๋ฌธ์ž์—ด์„ ์ฐพ์•„๋ณธ๋‹ค.
    7. ํด๋กœ์ €๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด 0๋ณด๋‹ค ํฐ ์–ด๋–ค ์ •์ˆ˜์˜ ๋ฌธ์ž์—ด ํ‘œํ˜„์ด๋“  ์ƒ์„ฑ ๊ฐ€๋Šฅํ•˜๋‹ค.
    8. digitNames ๋”•์…”๋„ˆ๋ฆฌ์—์„œ ๊ฐ€์ ธ์˜จ ๋ฌธ์ž์—ด์„ output ์•ž์— ์ถ”๊ฐ€ํ•˜์—ฌ ์‚ฌ์‹ค์ƒ ์ˆ˜์น˜ ๊ฐ’์˜ ๋ฌธ์ž์—ด ๋ฒ„์ „์„ ์—ญ์ˆœ์œผ๋กœ ์ œ์ž‘ํ•œ๋‹ค. (ํ‘œํ˜„์‹ nubmer % 10 ์€ 16์ด๋ฉด 6, 58์ด๋ฉด 8, 510์ด๋ฉด 0์„ ๋ฐ˜ํ™˜)
    9. ๊ทธ๋Ÿฐ ๋‹ค์Œ, number ๋ณ€์ˆ˜๋ฅผ 10 ์œผ๋กœ ๋‚˜๋ˆˆ๋‹ค. ์ •์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ๋‚˜๋ˆ—์…ˆ์ค‘์— ๊ฐ’์„ ์ž˜๋ผ 16์ด๋ฉด 1, 510์ด๋ฉด 51์ด ๋œ๋‹ค.
    10. ์ด ๊ณผ์ •์„ ๋ฐ˜๋ณตํ•˜๋‹ค๊ฐ€ 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)
}

์—ฌ๊ธฐ์„œ ํด๋กœ์ €๊ฐ€ ์‹คํ–‰๋˜๋Š” ์ˆœ์„œ๋ฅผ ์‚ดํŽด๋ณด์ž.

  1. ํด๋กœ์ €๊ฐ€ someFunctionWithEscapingClosure ํ•จ์ˆ˜์˜ completionHandler ์ธ์ž๋กœ ์ „๋‹ฌ๋จ.
  2. ํด๋กœ์ € completionHandler ์ด ์™ธ๋ถ€์—์„œ ์„ ์–ธ๋œ Array์— ์ถ”๊ฐ€ํ•จ.
  3. someFunctionWithEscapingClosure ํ•จ์ˆ˜๊ฐ€ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์ข…๋ฃŒ๋จ.
  4. ํด๋กœ์ € 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)

 

[Swift] Escaping ํด๋กœ์ € (@escaping)

์ •์˜ Escaping ํด๋กœ์ €๋Š” ํด๋กœ์ €๊ฐ€ ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ์ „๋‹ฌ๋์„ ๋•Œ, ํ•จ์ˆ˜์˜ ์‹คํ–‰์ด ์ข…๋ฃŒ๋œ ํ›„ ์‹คํ–‰๋˜๋Š” ํด๋กœ์ € ์ž…๋‹ˆ๋‹ค. Non-Escaping ํด๋กœ์ €๋Š” ์ด์™€ ๋ฐ˜๋Œ€๋กœ ํ•จ์ˆ˜์˜ ์‹คํ–‰์ด ์ข…๋ฃŒ๋˜๊ธฐ ์ „์— ์‹คํ–‰๋˜๋Š” ํด๋กœ์ €

jusung.github.io


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์˜ ์‚ฌ์šฉ๋ฐฉ๋ฒ•๊ณผ ์˜ˆ์‹œ์— ๋Œ€ํ•ด์„œ ์„ค๋ช…์ด ์ž˜ ๋œ ๊ธ€

[Swift] @autoclosure๋ž€?

 

[Swift] @autoclosure๋ž€?

์ •์˜ @autoclosure๋Š” ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ์ „๋‹ฌ๋˜๋Š” ์ฝ”๋“œ๋ฅผ ๊ฐ์‹ธ์„œ ์ž๋™์œผ๋กœ ํด๋กœ์ €๋กœ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค. ๋‹ค์‹œ๋งํ•ด ์ผ๋ฐ˜ ํ‘œํ˜„์˜ ์ฝ”๋“œ๋ฅผ ํด๋กœ์ € ํ‘œํ˜„์˜ ์ฝ”๋“œ๋กœ ๋งŒ๋“ค์–ด ์ฃผ๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

jusung.github.io

 

 

์ฝ์–ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์ž˜๋ชป๋œ ๋ถ€๋ถ„์ด ์žˆ์œผ๋ฉด ์–ธ์ œ๋“ ์ง€ ๋ง์”€ํ•ด์ฃผ์„ธ์š”. ์•„์ง ํด๋กœ์ €์— ๋Œ€ํ•ด์„œ ๋ชจ๋“  ๊ฒƒ์„ ์ดํ•ดํ•˜์ง€ ์•Š์€ ์ƒํ™ฉ์ด๋ผ ํ‹€๋ ธ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค ใ… ใ…  ํด๋กœ์ €๋ฅผ ์ •๋ณตํ•˜๋Š” ๊ทธ๋‚ ๊นŒ์ง€ ๊ด€๋ จ ํฌ์ŠคํŒ…์€ ๋๊นŒ์ง€ ๊ณ„์†๋ฉ๋‹ˆ๋‹ค ํ—ˆํ—ˆ

๋ฐ˜์‘ํ˜•