iOS/🟠 Swift

[Swift] - Autoclosuresλž€?

woozzang 2021. 3. 2. 20:32

μ˜€ν† ν΄λ‘œμ €λŠ” 

ν•¨μˆ˜μ— μ•„κ·œλ¨ΌνŠΈλ‘œ 전달 된 ν‘œν˜„μ‹μ„ λž˜ν•‘ν•˜μ—¬ μžλ™μœΌλ‘œ μƒμ„±λ˜λŠ” ν΄λ‘œμ €  이닀.

#μ΄λ¦„μ˜ 유래: '{ }' 없이 ν‘œν˜„μ‹λ§Œ 가지고 μžλ™μœΌλ‘œ ν΄λ‘œμ €λ‘œ μƒμ„±λ˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.


 

μœ„ λ¬Έμž₯은 무슨 λœ»μΌκΉŒμš”?

 

1. 'ν‘œν˜„μ‹μ„ λž˜ν•‘ ν•œλ‹€λŠ” 것' 은 ν΄λ‘œμ €κ°€ μ•„λ‹Œ 것을 ν΄λ‘œμ €λ‘œ λ§Œλ“€μ–΄ μ€€λ‹€λŠ” 의미둜 μ‚¬μš©λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

2. ν•¨μˆ˜ μ •μ˜λΆ€μ˜ νŒŒλΌλ―Έν„°μ˜ νƒ€μž… μ•žμ— @autoclosure 속성을 뢙이면, μ•„κ·œλ¨ΌνŠΈλ‘œ λͺ…μ‹œμ  ν΄λ‘œμ € λŒ€μ‹  ν΄λ‘œμ € μ•ˆμ˜ ν‘œν˜„μ‹λ§Œ μ „λ‹¬ν•˜λ©΄ λ©λ‹ˆλ‹€.

func exampleFunc(param: @autoclosure () -> Int ) {
	...
}

 

 

νŠΉμ§• 1. μ˜€ν† ν΄λ‘œμ €λŠ” μ–΄λ– ν•œ μ•„κ·œλ¨ΌνŠΈλ„ 받지 μ•ŠμŠ΅λ‹ˆλ‹€.

λŒ€μ‹  μ˜€ν† ν΄λ‘œμ €κ°€ 호좜될 λ•Œ λž˜ν•‘ λ˜μ–΄μžˆλŠ” ν‘œν˜„μ‹μ˜ 값을 λ°˜ν™˜ν•©λ‹ˆλ‹€.

 

μ˜€ν† ν΄λ‘œμ €μ—λŠ” λͺ…λ°±ν•œ ν΄λ‘œμ € ν‘œν˜„μ‹ λŒ€μ‹  일반적인 ν‘œν˜„μ‹μ„ μž‘μ„±ν•˜λ©΄ μžλ™μœΌλ‘œ ν΄λ‘œμ €λ‘œ λž˜ν•‘λ˜κΈ° λ•Œλ¬Έμ— 브레이슀λ₯Ό μƒλž΅ν•©λ‹ˆλ‹€.

 

μ•„κ·œλ¨ΌνŠΈλ‘œ μ˜€ν† ν΄λ‘œμ €λ₯Ό μ‚¬μš©ν•˜λŠ” ν•¨μˆ˜λ“€μ„ ν˜ΈμΆœν•˜λŠ” 일은 ν”ν•©λ‹ˆλ‹€.

 

ν•˜μ§€λ§Œ μœ„μ™€ 같은 μ’…λ₯˜μ˜ ν•¨μˆ˜λ“€μ„ κ΅¬ν˜„ν•˜λŠ” 일은 ν”ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

μ € μ—­μ‹œλ„ κ΅¬ν˜„λ³΄λ‹€λŠ” μ½”λ“œλ₯Ό μ΄ν•΄ν•˜κΈ° μœ„ν•˜μ—¬ μ˜€ν† ν΄λ‘œμ €λ₯Ό κ³΅λΆ€ν•˜μ˜€μŠ΅λ‹ˆλ‹€.


 

νŠΉμ§• 2. μ˜€ν† ν΄λ‘œμ €λŠ” 평가λ₯Ό μ§€μ—°μ‹œμΌœμ€λ‹ˆλ‹€.

μ™œλƒν•˜λ©΄ ν΄λ‘œμ €λŠ” 호좜되기 μ „κΉŒμ§€ λ‚΄λΆ€ μ½”λ“œλ₯Ό μ‹€ν–‰μ‹œν‚€μ§€ μ•ŠκΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.

 

평가λ₯Ό μ§€μ—°μ‹œν‚¨λ‹€?

평가(evaluate) = ν‘œν˜„μ‹μ„ μ‹€ν–‰μ‹œν‚¨λ‹€ (run the code)

 

ν‰κ°€μ˜ 지연은 μ‚¬μ΄λ“œ μ΄νŽ™νŠΈκ°€ μžˆλŠ” μ½”λ“œλ‚˜, 계산 λΉ„μš©μ΄ 많이 λ“œλŠ” μ½”λ“œμ— μœ μš©ν•©λ‹ˆλ‹€.

κ΄€λ ¨ κΈ€: μ‚¬μ΄λ“œ μ΄νŽ™νŠΈ

 

μš°λ¦¬κ°€ μ½”λ“œκ°€ ν‰κ°€λ˜λŠ” μ‹œμ μ„ μ œμ–΄ν•  수 있기 λ•Œλ¬Έμž…λ‹ˆλ‹€.

 

μ•„λž˜μ˜ μ½”λ“œλŠ” ν΄λ‘œμ €κ°€ μ–΄λ–»κ²Œ 평가λ₯Ό μ§€μ—°μ‹œν‚€λŠ”μ§€ 보여주고 μžˆμŠ΅λ‹ˆλ‹€.

 

var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
print(customersInLine.count)
// Prints "5"


// customProvider κ°€ ν˜ΈμΆœλ˜λŠ” μ‹œμ μ— μ‹€ν–‰λ©λ‹ˆλ‹€.

/* 1 */
//() -> String νƒ€μž…μ˜ ν΄λ‘œμ € ( remove(at: ) ν•¨μˆ˜λŠ” ν΄λ‘œμ € ν˜ΈμΆœμ‹œμ— 싀행됨 )

let customerProvider = { customersInLine.remove(at: 0) }

/* 2 */
// String νƒ€μž…μ˜ μƒμˆ˜ ( remove(at: ) ν•¨μˆ˜κ°€ λ°”λ‘œ 싀행됨 ) 

let customerProvider2 = customersLine.remove(at: 0)

print(customersInLine.count)
// Prints "5"

// remove(at:) 이 μ‹€ν–‰λ˜λŠ” μ‹œμ 
print("Now serving \(customerProvider())!")
// Prints "Now serving Chris!"
print(customersInLine.count)
// Prints "4"

 

customersInLine  λ°°μ—΄μ˜ 첫 번째 elementκ°€ ν΄λ‘œμ € λ‚΄λΆ€μ˜ μ½”λ“œμ—μ„œ μ‚­μ œλ˜μ—ˆμ§€λ§Œ, ν΄λ‘œμ €κ°€ μ‹€μ œλ‘œ 호좜되기 μ „κΉŒμ§€λŠ” μ‚­μ œλ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

 

ν΄λ‘œμ €κ°€ 이후에도 ν˜ΈμΆœλ˜μ§€ μ•ŠλŠ”λ‹€λ©΄, ν΄λ‘œμ € λ‚΄λΆ€μ˜ ν‘œν˜„μ‹μ€ μ ˆλŒ€λ‘œ ν‰κ°€λ˜μ§€ μ•Šμ„ 것이며, λ”°λΌμ„œ λ°°μ—΄μ˜ elementλŠ” μ‚­μ œλ˜μ§€ μ•Šμ„ κ²ƒμž…λ‹ˆλ‹€.

 

μ—¬κΈ°μ„œ  customerProvider λŠ” () -> String νƒ€μž…μ˜ ν•¨μˆ˜μž„μ„ 인지해야 ν•©λ‹ˆλ‹€.

무엇을 λ§ν•˜κ³  μ‹Άμ€μ§€λŠ” μœ„ μ½”λ“œμ˜ /* 1 */ 와 /* 2 */ μ½”λ“œλ₯Ό 비ꡐ해보면 이해할 수 μžˆμŠ΅λ‹ˆλ‹€..


 

ν•¨μˆ˜μ˜ μ•„κ·œλ¨ΌνŠΈλ‘œ ν΄λ‘œμ €λ₯Ό 전달할 λ•Œλ„ λ™μΌν•œ λ™μž‘μ„ κΈ°λŒ€ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

 

ν΄λ‘œμ €λ₯Ό νŒŒλΌλ―Έν„°λ‘œ 전달할 λ•Œ, ν΄λ‘œμ €λŠ” μ‹€ν–‰λ˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— μ•ˆμ˜ ν‘œν˜„μ‹μ΄ ν‰κ°€λ˜μ§€ μ•Šκ³ , ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ ν˜ΈμΆœν•  λ•Œμ— ν‰κ°€λ˜λŠ” κ²ƒμž…λ‹ˆλ‹€. (= ν‰κ°€μ˜ 지연 )

// customersInLine is ["Alex", "Ewa", "Barry", "Daniella"]

// λͺ…μ‹œμ  ν΄λ‘œμ €λ₯Ό νŒŒλΌλ―Έν„°λ‘œ λ°›λŠ” ν•¨μˆ˜
func serve1(customer customerProvider: () -> String) {
    print("Now serving \(customerProvider())!")
}
serve(customer: { customersInLine.remove(at: 0) } )
// Prints "Now serving Alex!"

// μ˜€ν† ν΄λ‘œμ €λ₯Ό νŒŒλΌλ―Έν„°λ‘œ λ°›λŠ” ν•¨μˆ˜
func serve2(customer customerProvider: @autoclosure () -> String) {
    print("Now serving \(customerProvider())!")
}

serve(customer: customersInLine.remove(at: 0) )

 

serve(customer:) ν•¨μˆ˜λŠ” μ˜€ν† ν΄λ‘œμ €κ°€ μ•„λ‹Œ 고객의 이름을 λ°˜ν™˜ν•˜λŠ” κΈ°λŠ₯을 ν•˜λŠ” λͺ…μ‹œμ  ν΄λ‘œμ €λ₯Ό λ°›κ³  μžˆμŠ΅λ‹ˆλ‹€.

λͺ…μ‹œμ  ν΄λ‘œμ €λž€  { } (Curly Braces) 둜 감싸져 μžˆλŠ” λ¬Έλ²•μœΌλ‘œ μž‘μ„±λœ ν΄λ‘œμ €λ₯Ό μ˜λ―Έν•©λ‹ˆλ‹€.

 

μ˜€ν† ν΄λ‘œμ €λ₯Ό 톡해 λ™μΌν•œ λ™μž‘μ„ κΈ°λŒ€ν•˜λ €λ©΄ μ‚¬μš©ν•˜λ €λŠ” νŒŒλΌλ―Έν„°μ˜ νƒ€μž… μ•žμͺ½μ—  @autoclosure 속성을 λΆ™μ—¬μ£Όλ©΄ λ©λ‹ˆλ‹€.


 

κ²°λ‘ 

μ˜€ν† ν΄λ‘œμ €λ₯Ό μ‚¬μš©ν•˜λŠ” 것과 λͺ…μ‹œμ  ν΄λ‘œμ €λ₯Ό μ‚¬μš©ν•˜λŠ” 것 차이점은

 

μ˜€ν† ν΄λ‘œμ €λ₯Ό μ‚¬μš©ν•˜λŠ” ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•Œ, { } κ°€ μ—†λŠ” ν‘œν˜„μ‹λ§Œ 전달해도 μ•Œμ•„μ„œ ν΄λ‘œμ €λ‘œ λž˜ν•‘ν•΄ μ€€λ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€.


μ•„λž˜μ˜ μ½”λ“œλ₯Ό 보면

 

serve2(customer:)λŠ” λ§ˆμΉ˜ remove(at: )  의 λ°˜ν™˜ 값인

 

String νƒ€μž…μ„ νŒŒλΌλ―Έν„°λ‘œ λ°›λŠ” 것 κ°™μ§€λ§Œ, 사싀은 ν΄λ‘œμ €λ₯Ό λ°›λŠ” κ²ƒμ΄λΌλŠ” 것!
맀우 μ€‘μš”!!


λ•Œλ¬Έμ— μ½”λ“œλ₯Ό μ½λŠ” μ‚¬λžŒμ—κ²Œ ν˜Όλ™μ„ 쀄 수 μžˆμŠ΅λ‹ˆλ‹€.

 

// <λͺ…μ‹œμ  ν΄λ‘œμ €λ₯Ό μ „λ‹¬ν•˜μ—¬ 호좜> '{ }' 브레이슀λ₯Ό λ„£μ–΄μ£Όμ–΄ λͺ…μ‹œμ μœΌλ‘œ ν΄λ‘œμ €λ₯Ό ν‘œν˜„
serve1(customer: { customersInLine.remove(at: 0) })

// <μ˜€ν†  ν΄λ‘œμ €λ₯Ό μ „λ‹¬ν•˜μ—¬ 호좜> '{ }' 브레이슀 없이 ν‘œν˜„μ‹λ§Œ 전달
serve2(customer: customerInLine.remove(at: 0))


 

+ ) μ˜€ν† ν΄λ‘œμ €λŠ” ν›„ν–‰ ν΄λ‘œμ €(trailing closures) 둜 κΈ°μˆ ν•  수 μ—†μŠ΅λ‹ˆλ‹€. ( 컴파일 μ—λŸ¬ 확인 )

 

ν›„ν–‰ ν΄λ‘œμ €μ˜ syntax λŠ” λͺ…μ‹œμ  ν΄λ‘œμ €μ˜ 전달과 κ²°κ΅­ κ°™μ•„μ§€λ―€λ‘œ 그런 것 κ°™μŠ΅λ‹ˆλ‹€.

 


N O T E

 

Context 와 ν•¨μˆ˜ 이름을 톡해 평가가 μ§€μ—°λ˜μ—ˆμŒμ„ λͺ…ν™•νžˆ ν•΄μ£Όμ–΄μ•Ό 이해가 μ–΄λ €μš΄ μ½”λ“œκ°€ λ˜λŠ” 것을 방지할 수 μžˆμŠ΅λ‹ˆλ‹€.


 

 

 

끝!