Skip to content

Latest commit

Β 

History

History
364 lines (269 loc) Β· 8.53 KB

closure.md

File metadata and controls

364 lines (269 loc) Β· 8.53 KB

closure

  • μ½”λ“œμ—μ„œ μ‚¬μš©ν•˜κ±°λ‚˜ 전달할 수 μžˆλŠ” 독립적인 κΈ°λŠ₯을 가진 λΈ”λŸ­
  • ν•¨μˆ˜λ„ ν΄λ‘œμ €μ˜ 일쒅

μ „μ—­(Global) ν•¨μˆ˜μ™€ 쀑첩(Nested) ν•¨μˆ˜λŠ” 사싀 ν΄λ‘œμ €μ˜ νŠΉμˆ˜ν•œ μ˜ˆμ— ν•΄λ‹Ή.
ν΄λ‘œμ €λŠ” λ‹€μŒ 3가지 쀑 ν•œ 가지 μœ ν˜•μ„ 가짐

  • Global functions: 이름을 가지며, μ–΄λ–€ 값도 μΊ‘μ³ν•˜μ§€ μ•ŠλŠ” ν΄λ‘œμ €
  • Nested functions: 이름을 가지며, 감싸고 μžˆλŠ” ν•¨μˆ˜μ˜ 값을 μΊ‘μ³ν•˜λŠ” ν΄λ‘œμ €
  • Closure: μ£Όλ³€ λ¬Έλ§₯(Context)의 값을 캑쳐할 수 있으며, κ°„λ‹¨ν•œ λ¬Έλ²•μœΌλ‘œ 쓰여진 이름 μ—†λŠ” ν΄λ‘œμ €

Global functions

μ™ΈλΆ€ν•¨μˆ˜

print(1)
max(1, 2)
func globalFunction() { } //μ™ΈλΆ€, λ°”κΉ₯μ—μ„œ μ“°μ΄λŠ” 것.

Nested functions

μ€‘μ²©ν•¨μˆ˜

func outsideFunction() -> () -> () { //ν•¨μˆ˜λ₯Ό λ¦¬ν„΄νƒ€μž…μœΌλ‘œ λ‹€λ£Έ.
  var x = 0
  
  func nestedFunction() { //μ€‘μ²©ν•¨μˆ˜: λ°”κΉ₯μ—μ„œ varμ„ μ–Έ (κΈ€λ‘œλ²ŒνŽ‘μ…˜), λ‚΄λΆ€μ—μ„œ 이용
    x += 1    // κ·Έ μžμ‹ μ˜ ν•¨μˆ˜κ°€ 가지지 μ•Šμ€ 값을 μ‚¬μš©
    print(x)
  }
  
  return nestedFunction
}
let nestedFunction = outsideFunction()
nestedFunction()
nestedFunction()
nestedFunction()

Closure

κΈ°λ³Έν˜•

 Closure Expression Syntax
 
 { (νŒŒλΌλ―Έν„°) -> λ¦¬ν„΄νƒ€μž… in
   싀행ꡬ문
 }
func aFunction() { //viod νƒ€μž…
  print("This is a function.")
}
aFunction()
aFunction()

({
  print("This is a closure.")
})()

Save closure to variable

// ν΄λ‘œμ €λ₯Ό λ³€μˆ˜μ— λ‹΄μ•„ 이름 λΆ€μ—¬ κ°€λŠ₯
let closure = { //voidνƒ€μž…
  print("This is a closure.")
}
closure()
closure()


// ν•¨μˆ˜λ„ λ³€μˆ˜λ‘œ μ €μž₯ κ°€λŠ₯
var function/* : () -> () */= aFunction //viodνƒ€μž…
function()


// 같은 νƒ€μž…μΌ 경우 ν•¨μˆ˜λ‚˜ ν΄λ‘œμ € 관계없이 μΉ˜ν™˜ κ°€λŠ₯
function = closure
function()
type(of: function)
type(of: closure)

Closure Syntax

// νŒŒλΌλ―Έν„° + λ°˜ν™˜ νƒ€μž…μ„ 가진 ν•¨μˆ˜
func funcWithParamAndReturnType(_ param: String) -> String {
  return param + "!"
}
print(funcWithParamAndReturnType("function"))

//μŠ€νŠΈλ§μ„ λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜, return λ‚΄κ°€μ›ν•˜λŠ” νŒŒλΌλ―Έν„° 전달.



// νŒŒλΌλ―Έν„° + λ°˜ν™˜ νƒ€μž…μ„ 가진 ν΄λ‘œμ €
// Type Annotation
let closureWithParamAndReturnType1: (String) -> String = { param in
  return param + "!"
}
print(closureWithParamAndReturnType1("closure"))

// Argument Label은 μƒλž΅. ν•¨μˆ˜μ˜ Argument Label을 (_)둜 μƒλž΅ν•œ 것과 동일


// νŒŒλΌλ―Έν„° + λ°˜ν™˜ νƒ€μž…μ„ 가진 ν΄λ‘œμ € // νƒ€μž…μ„ 내뢀에 μ“Έ μˆ˜λ„ 있음.
let closureWithParamAndReturnType2 = { (param: String) -> String in
  return param + "!"
}
print(closureWithParamAndReturnType2("closure"))


// νŒŒλΌλ―Έν„° + λ°˜ν™˜ νƒ€μž…μ„ 가진 ν΄λ‘œμ €
// Type Inference //리턴과 μ†Œκ΄„ν˜Έλ₯Ό μƒλž΅ν• μˆ˜λ„ 있음.
let closureWithParamAndReturnType3 = { param in
  param + "!"
}
print(closureWithParamAndReturnType3("closure"))

Question

  • λ¬Έμžμ—΄μ„ μž…λ ₯λ°›μœΌλ©΄ κ·Έ λ¬Έμžμ—΄μ˜ 개수λ₯Ό λ°˜ν™˜ν•˜λŠ” 클둜져 κ΅¬ν˜„
  • 숫자 ν•˜λ‚˜λ₯Ό μž…λ ₯받은 λ’€ 1을 λ”ν•œ 값을 λ°˜ν™˜ν•˜λŠ” 클둜져 κ΅¬ν˜„
// 1번 문제 예.   "Swift" -> 5

let comString = { (origin: String) -> Int in
   return origin.count
}
print(comString("swift"))

//1λ²ˆμ— 3번 μ μš©ν•˜λ €λ©΄ νƒ€μž… λͺ…μ‹œν•΄μ€˜μ•Όν•¨.
let counting: (String) -> Int = { param in
    param.count
}
counting("swift")

// 2번 문제 예.   5 -> 6

let comInt = {(master: Int) -> Int in
    return master + 1
}
print(comInt(5))

//
let byInt = { origin in
    origin + 1
}
print(byInt(4))

Answer

/// λ¬Έμžμ—΄μ„ μž…λ ₯λ°›μœΌλ©΄ κ·Έ λ¬Έμžμ—΄μ˜ 개수λ₯Ό λ°˜ν™˜ν•˜λŠ” 클둜져 κ΅¬ν˜„

// 1단계 - ν•¨μˆ˜λ‘œ 생각
func stringCount(str: String) -> Int {
  return str.count
}
print(stringCount(str: "Swift"))

// 2단계 - ν΄λ‘œμ €λ‘œ λ³€ν˜•
let stringCount = { (str: String) -> Int in
  return str.count
}
stringCount("Swift")

// 3단계 - 문법 μ΅œμ ν™”
let stringCount2: (String) -> Int = { $0.count }



/// 숫자 ν•˜λ‚˜λ₯Ό μž…λ ₯받은 λ’€ 1을 λ”ν•œ 값을 λ°˜ν™˜ν•˜λŠ” 클둜져 κ΅¬ν˜„
//func addOne = (num: Int) -> Int
//return num + 1

let addOne = { (num: Int) -> Int in
  return num + 1
}
addOne(5)

let addTwo: (Int) -> Int = { $0 + (5) }
addTwo(5)

Closureμž₯점

  • 문법 κ°„μ†Œν™” /가독성
  • 지연생성 / μ‹€μ œλ‘œ μ½”λ“œλ₯Ό μ‚¬μš©ν•  μ‹œκΈ°κ°€ μ™”μ„λ•Œ, λ©”λͺ¨λ¦¬μ— μ˜¬λΌκ°€λŠ”κ²ƒ.
  • μ£Όλ³€ μ»¨ν…μŠ€νŠΈμ˜ 값을 μΊ‘μ³ν•˜μ—¬ μž‘μ—… μˆ˜ν–‰κ°€λŠ₯

Syntax Optimization

###Swift ν΄λ‘œμ € 문법 μ΅œμ ν™”

  • λ¬Έλ§₯을 톡해 λ§€κ°œλ³€μˆ˜ 및 λ°˜ν™˜ 값에 λŒ€ν•œ νƒ€μž… μΆ”λ‘ 
  • 단일 ν‘œν˜„μ‹ ν΄λ‘œμ €μ—μ„œμ˜ λ°˜ν™˜ ν‚€μ›Œλ“œ μƒλž΅ /(returnμƒλž΅)
  • μΆ•μ•½ 인수λͺ… //($0)
  • ν›„ν–‰ ν΄λ‘œμ € 문법
// μž…λ ₯된 λ¬Έμžμ—΄μ˜ 개수λ₯Ό λ°˜ν™˜ν•˜λŠ” ν΄λ‘œμ €λ₯Ό ν•¨μˆ˜μ˜ νŒŒλΌλ―Έν„°λ‘œ μ „λ‹¬ν•˜λŠ” 예
func performClosure(param: (String) -> Int) { //param: ν•¨μˆ˜λ₯Ό λ§€κ°œλ³€μˆ˜λ‘œ λ°›λŠ” ν•¨μˆ˜. param은 input을 string으둜 λ°›κ³ , λ°˜ν™˜μ„ int둜 ν•œλ‹€λŠ” 뜻.
  param("Swift")
}

performClosure(param: { (str: String) -> Int in //λͺ¨λ“  λ‚΄μš©μ„ λ‹€ 적은 것.
  return str.count
})

performClosure(param: { (str: String) in //.countκ°€ Int이기 λ•Œλ¬Έμ— μƒλž΅κ°€λŠ₯.
  return str.count
})

performClosure(param: { str in //νŽ‘μ…˜μ— 이미 String을 λ°›κ³  μžˆλ‹€λŠ” κ±Έ μ•Œμˆ˜ μžˆμ–΄μ„œ Sting도 μƒλž΅κ°€λŠ₯.
  return str.count
})

performClosure(param: { //λ§€κ°œλ³€μˆ˜λͺ…도 μƒλž΅κ°€λŠ₯. $0,$1,$2 λ“±μœΌλ‘œ ν‘œν˜„κ°€λŠ₯.
  return $0.count
})

performClosure(param: { //return μƒλž΅κ°€λŠ₯.
  $0.count
})

performClosure(param: ) { //paramκ°€ ν•œκ°œμΌ 경우. κ΄„ν˜Έ λ‹«μœΌλ©΄, param을 λ§ˆμ§€λ§‰ νŒŒλΌλ―Έν„° κ°’μœΌλ‘œ λ°›μ•„λ“€μž„.
  $0.count
}

performClosure() { //λ§ˆμ§€λ§‰ νŒŒλΌλ―Έν„°λΌλ©΄, (param: )을 μƒλž΅ν•΄λ„ 됨.
  $0.count
}

performClosure { $0.count } //μ†Œκ΄„ν˜Έλ„ μƒλž΅κ°€λŠ₯.


//νƒ€μž…μΆ”λ‘ μ„ λͺ»ν•˜λŠ” κ²½μš°μ—λŠ” νƒ€μž…μ„ λͺ¨λ‘ μ μ–΄μ€˜μ•Όν•˜μ§€λ§Œ, 좔둠이 κ°€λŠ₯ν•˜λ‹€λ©΄ μ€„μ—¬λ‚˜κ°ˆ 수 있음.
//νŒŒλΌλ―Έν„°κ°€ 1개인경우 μ΅œμ’…κΉŒμ§€ κ°€λŠ₯ν•˜μ§€λ§Œ, νŒŒλΌλ―Έν„°κ°€ λ‹€μˆ˜μΌ 경우, μ΅œμ’…κΉŒμ§€λŠ” λΆˆκ°€.($0,$1λ“±μœΌλ‘œ ν™œμš©ν•˜κ±°λ‚˜ return μƒλž΅..) 

//νŽ‘μ…˜ λ‹€μŒμ—, ν΄λ‘œμ € μ“°μ΄λŠ” 경우, ν•¨μˆ˜κ°€ λ“€μ–΄κ°€λŠ”κ±΄μ§€, ν΄λ‘œμ €κ°€ λ“€μ–΄κ°€λŠ” 건지 ꡬ뢄해야함. 

Inline closure

  • ν•¨μˆ˜μ˜ 인수(Argument)둜 λ“€μ–΄κ°€λŠ” ν΄λ‘œμ €

ν•¨μˆ˜μ΄μš© 버전

func closureParamFunction(closure: () -> Void) {
  closure()
}
func printFunction() {
  print("Swift Function!")
}
let printClosure = {
  print("Swift Closure!")
}

closureParamFunction(closure: printFunction)
closureParamFunction(closure: printClosure)

인라인 ν΄λ‘œμ € 버전

// 인라인 ν΄λ‘œμ € - λ³€μˆ˜λ‚˜ ν•¨μˆ˜μ²˜λŸΌ 쀑간 맀개체 없이 μ‚¬μš©λ˜λŠ” ν΄λ‘œμ €
closureParamFunction(closure: {
  print("Inline closure - Explicit closure parameter name")
})

Trailing Closure

  • ν•¨μˆ˜μ˜ κ΄„ν˜Έκ°€ λ‹«νžŒ 후에도 인수둜 μ·¨κΈ‰λ˜λŠ” ν΄λ‘œμ €
  • ν•¨μˆ˜μ˜ λ§ˆμ§€λ§‰ 인수(Argument)μ—λ§Œ μ‚¬μš© κ°€λŠ₯ν•˜κ³  ν•΄λ‹Ή 인수λͺ…은 μƒλž΅
  • ν•˜λ‚˜μ˜ 라인에 λ‹€ ν‘œν˜„ν•˜μ§€ λͺ»ν•  κΈ΄ ν΄λ‘œμ Έμ— 유용

κΈ°λ³Έν˜•

//λ§ˆμ§€λ§‰ 인수λ₯Ό μƒλž΅ν•  수 μžˆλŠ”κ²ƒ - νŠΈλ ˆμ΄λ‹ ν΄λ‘œμ € 
// ν›„μœ„ λ˜λŠ” ν›„ν–‰ ν΄λ‘œμ €
// closureParamFunction { <#code#> }

closureParamFunction(closure: {
  print("Inline closure - Explicit closure parameter name")
})
closureParamFunction() {
  print("Trailing closure - Implicit closure parameter name")
}
closureParamFunction {
  print("Trailing closure - Implicit closure parameter name")
}
func multiClosureParams(closure1: () -> Void, closure2: () -> Void) {
  closure1()
  closure2()
}

//인라인 ν˜•μ‹
multiClosureParams(closure1: {
  print("inline")
}, closure2: {
  print("inline")
})

//νŠΈλ ˆμ΄λ‹ ν˜•μ‹
//λ§ˆμ§€λ§‰ μΈμˆ˜κ°€ μ‹œμž‘ν•˜κΈ° 직전에 닫아버림.  
multiClosureParams(closure1: {
  print("inline")
}) {
  print("trailing")
}

Question

  • μ •μˆ˜λ₯Ό ν•˜λ‚˜ μž…λ ₯λ°›μ•„ 2의 배수 μ—¬λΆ€λ₯Ό λ°˜ν™˜ν•˜λŠ” 클둜져
  • μ •μˆ˜λ₯Ό 두 개 μž…λ ₯ λ°›μ•„ κ³±ν•œ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•˜λŠ” 클둜져
//μ •μˆ˜λ₯Ό ν•˜λ‚˜ μž…λ ₯λ°›μ•„ 2의 배수 μ—¬λΆ€λ₯Ό λ°˜ν™˜ν•˜λŠ” 클둜져
let Question = { (origin: Int) -> Bool in
    return origin % 2 == 0
}

//
let Question1 = {$0 % 2 == 0}
Question1(5)
Question1(6)
/// μ •μˆ˜λ₯Ό 두 개 μž…λ ₯λ°›μ•„ κ³±ν•œ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•˜λŠ” 클둜져
let multiplyTwoNumbers = { (op1: Int, op2: Int) -> Int in
  return op1 * op2
}
// Optimization
let multiplyTwoNumbers2: (Int, Int) -> Int = { $0 * $1 }

multiplyTwoNumbers(20, 5)
multiplyTwoNumbers(5, 10)
multiplyTwoNumbers2(5, 10)