[UMC] 1μ£Όμ°¨πŸ’» - λΆ€μŠ€νŠΈμ½”μŠ€ μ½”ν‹€λ¦° μˆ˜κ°•(4)

MadelineπŸ‘©πŸ»β€πŸ’»Β·2022λ…„ 9μ›” 23일
0

kotlin study

λͺ©λ‘ 보기
4/19

πŸš— 4. ν•¨μˆ˜ 가지고 놀기

1. κ³ μ°¨ν•¨μˆ˜μ™€ λžŒλ‹€μ‹ (1)

{λžŒλ‹€ ν•¨μˆ˜μ— μ‚¬μš©ν•  λ§€κ°œλ³€μˆ˜ -> λ°˜ν™˜ν•  식}

* μžλ£Œν˜•μ„ μΆ”λ‘ ν•  수 있게 써야 ν‘œν˜„λœλ‹€!

🌎 λ°˜ν™˜ μžλ£Œν˜•μ΄ μ—†λŠ” 경우: () -> Unit
🌎 λ§€κ°œλ³€μˆ˜κ°€ ν•˜λ‚˜μΈ 경우: (Int)->Int**

val greet: () -> Unit = {println("Hello")} //λ°˜ν™˜κ°’λ„, μΈμžλ„ μ—†λŠ” 경우: 였λ₯Έμͺ½μ— ν™”μ‚΄ν‘œX

🌎 λžŒλ‹€μ‹ μ•ˆμ— λžŒλ‹€μ‹μ΄ μžˆλŠ” 경우**
val nestedLambda: ()->()->Unit = { { println("nested")} }
//μ€‘κ΄„ν˜Έ λ‘κ°œ!


ν•¨μˆ˜ μžμ²΄μ— λ°˜ν™˜μ„ ν•¨μˆ˜λ‘œ 쀄 수 있음

-λžŒλ‹€μ‹, κ³ μ°¨ν•¨μˆ˜ ν˜ΈμΆœν•˜κΈ°

1) 값에 μ˜ν•œ 호좜

: ν•¨μˆ˜κ°€ 인자둜 μ „λ‹¬λ˜λŠ” 경우: λžŒλ‹€μ‹ ν•¨μˆ˜λŠ” κ°’μœΌλ‘œ μ²˜λ¦¬λ˜μ–΄ κ·Έ μ¦‰μ‹œ ν•¨μˆ˜κ°€ μˆ˜ν–‰λœ 후에 값이 μ „λ‹¬λœλ‹€!

fun main(){
val result = callByValue(lambda())// 1️⃣ λžŒλ‹€μ‹ ν•¨μˆ˜λ₯Ό 호좜!
println(result)//5️⃣ result κ°’
}

fun callByValue(b: Boolean): Boolean{//3️⃣ b = 일반 λ³€μˆ˜ μžλ£Œν˜•μœΌλ‘œ μ„ μ–Έλœ λ§€κ°œλ³€μˆ˜
println("callByValue func")
return b//4️⃣
}

val lambda: () -> Boolean = {//λžŒλ‹€ ν‘œν˜„μ‹μ΄ 두쀄이면
println("lambda func")
true//2️⃣ λ§ˆμ§€λ§‰ ν‘œν˜„μ‹ λ¬Έμž₯의 κ²°κ³Όκ°€ λ°˜ν™˜!
}

2) λžŒλ‹€μ‹ 이름을 μ‚¬μš©ν•œ 호좜

fun main(){
val result = callByName(otherLambda)//1️⃣ λžŒλ‹€μ‹ μ΄λ¦„λ§Œ μ‚¬μš©ν•œ 경우 () ν•„μš” μ—†μŒ
println(result)//4️⃣ result
}
fun callByName(b: () -> Boolean): Boolean{//λ³€μˆ˜ b도 λžŒλ‹€μ‹!!
println("callByName func")
return b()// 2️⃣
}
val otherLambda: () -> Boolean = {//κ°’λ§Œ λ“€μ–΄κ°€λŠ”κ²Œ μ•„λ‹ˆλΌ, 이 λ‚΄μš©μ΄ λ‹€ λ“€μ–΄κ°€
println("otherLamda func")
true//3️⃣
}

3) λ‹€λ₯Έ ν•¨μˆ˜μ˜ 참쑰에 μ˜ν•œ 호좜

: λžŒλ‹€μ‹μΌλ•Œλ§Œ ν•¨μˆ˜μ˜ 인자둜 μ‚¬μš©ν•  수 μžˆλ‹€.

fun sum(x: Int, y: Int) = x+y

funcParam(3,2,sum) //였λ₯˜!!//sum이 λžŒλ‹€μ‹μ΄ μ•„λ‹ˆκΈ° λ•Œλ¬Έ!!!

=> funcParam(3,2,::sum) //참쑰방식!λ‚΄λΆ€μ μœΌλ‘œ λžŒλ‹€μ‹μ— λ§€μΉ˜ν•΄μ„œ κ°€μ Έμ˜΄

fun funcParam(a: Int, b: Int, c: (Int, Int) -> Int): Int{
return c(a,b)
}

2. κ³ μ°¨ν•¨μˆ˜μ™€ λžŒλ‹€μ‹ (2)

-λ§€κ°œλ³€μˆ˜ κ°œμˆ˜μ— 따라 λžŒλ‹€μ‹μ„ κ΅¬μ„±ν•˜λŠ” 방법

1) λ§€κ°œλ³€μˆ˜κ°€ μ—†λŠ” 경우

2) λ§€κ°œλ³€μˆ˜κ°€ 1개인 경우

//λ§€κ°œλ³€μˆ˜ aκ°€ ν•˜λ‚˜ μžˆλŠ” λžŒλ‹€μ‹ ν•¨μˆ˜
oneParam({a-> "Hello $a"})
oneParam{a-> "Hello $a"}
oneParam{"Hello $it"}//μ•žμ—μ„œ κ°€μ Έμ˜¨ λ³€μˆ˜ ν•˜λ‚˜(λ‘κ°œμΌκ²½μš° λŒ€μ²΄X)

fun oneParam(out: (String) -> String){
println(out("OneParam"))
}

3) λ§€κ°œλ³€μˆ˜κ°€ 2개 이상인 경우

//λ§€κ°œλ³€μˆ˜κ°€ 2개
moreParam{a,b -> "Hello $a $b"}

fun moreParam(out:(String, String)-> String){
println(out("One Param", "Two Param"))
}

/////////////
moreParam{_,b -> "Hello $b"}
//첫번째 λ¬Έμžμ—΄μ€ μ‚¬μš©μ•ˆν•΄

4) 일반 λ§€κ°œλ³€μˆ˜μ™€ λžŒλ‹€μ‹ λ§€κ°œλ³€μˆ˜λ₯Ό 같이 μ‚¬μš©

//μΈμžμ™€ ν•¨κ»˜ μ‚¬μš©ν•˜λŠ” 경우
//일반 λ§€κ°œλ³€μˆ˜μ™€ λžŒλ‹€μ‹ λ§€κ°œλ³€μˆ˜λ₯Ό 같이 μ‚¬μš©
withArgs("Arg1","Arg2",{a,b -> "Hello $a $b"})
//withArgs()의 λ§ˆμ§€λ§‰ 인자(out)κ°€ λžŒλ‹€μ‹μΈ 경우 () 뢄리 κ°€λŠ₯
withArgs("Arg1","Arg2") {a,b -> "Hello $a $b"}

fun withArgs(a: String, b: String, out:(String, String)->String){//a,b,out(λžŒλ‹€μ‹)
println(out(a,b))
}

5) 두 개의 λžŒλ‹€μ‹μ„ 가진 ν•¨μˆ˜

3. 읡λͺ…ν•¨μˆ˜, 인라인 ν•¨μˆ˜ (1)

1) 읡λͺ…ν•¨μˆ˜

-ν•¨μˆ˜κ°€ 이름이 μ—†λŠ” 것!
fun (x: Int, y: Int): Int = x+y//=={return x+y}

val add: (Int, Int) -> Int = fun(x,y) = x+y//읡λͺ…ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•œ add μ„ μ–Έ
//μž„μ‹œμ μœΌλ‘œ μ‚¬μš©ν•  λ•Œ μœ μš©ν•¨!
val result = add(10,2) //ν•¨μˆ˜μ²˜λŸΌ λ³΄μ΄μ§€λ§Œ, 처리된 κ²°κ³Ό λ¦¬ν„΄ν•œ 값을 λ‹΄κ³  μžˆλŠ” λ³€μˆ˜!!

val add = fun(x: Int, y: Int) = x+y

val add = {x: Int, y: Int -> x+y}

//μœ„μ²˜λŸΌ 읡λͺ…ν•¨μˆ˜μ™€ 읡λͺ…ν•¨μˆ˜ 쀑 ν•˜λ‚˜μΈ λžŒλ‹€μ‹μ€ 맀우 ν‘μ‚¬ν•˜λ‹€!

  • 차이점은 일반 읡λͺ…ν•¨μˆ˜μ—μ„œλŠ” return, break, continueκ°€ μ‚¬μš©κ°€λŠ₯ν•˜μ§€λ§Œ, λžŒλ‹€μ‹μ—μ„œλŠ” μ‚¬μš©ν•˜κΈ° μ–΄λ ΅λ‹€λŠ” 점이닀.

2) 인라인 ν•¨μˆ˜

: ν•¨μˆ˜κ°€ ν˜ΈμΆœλ˜λŠ” 곳에 λ‚΄μš©μ„ λͺ¨λ‘ 볡사!
-ν•¨μˆ˜μ˜ λΆ„κΈ° 없이 처리 -> μ„±λŠ₯ 증가!
-μ½”λ“œκ°€ λ³΅μ‚¬λ˜μ–΄ λ“€μ–΄κ°€κΈ° λ•Œλ¬Έμ— λŒ€κ°œ λ‚΄μš©μ€ 짧게 μž‘μ„±ν•œλ‹€
-인라인 ν•¨μˆ˜λŠ” λžŒλ‹€μ‹ λ§€κ°œλ³€μˆ˜λ₯Ό 가지고 μžˆλŠ” ν•¨μˆ˜ ν˜•νƒœλ₯Ό ꢌμž₯ν•œλ‹€.

inline ν•¨μˆ˜λŠ” main ν•¨μˆ˜ λ‚΄μ—μ„œ inlineν•¨μˆ˜ λ‚΄μš©μ΄ λ³΅μ‚¬λ˜μ–΄ κ·ΈλŒ€λ‘œ μ‹€ν–‰λœλ‹€. 반면 inline을 μ§€μš°κ³  μ‹€ν–‰ν•˜λ©΄ shortFunc()ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜μ—¬ μ‹€ν–‰λœλ‹€. [Kotlin - Show ByteCode - Decomplie] ν•΄μ„œ java μ½”λ“œλ‘œ 이 차이점을 ν™•μ‹€νžˆ λ³Ό 수 μžˆλ‹€.

inline 뢀뢄에 λ…Έλž€μƒ‰μœΌλ‘œ κ²½κ³ κ°€ λœ¨λŠ”λ°,
Expected performance impact from inlining is insignificant. Inlining works best for functions with parameters of functional types
인라인 ν•¨μˆ˜λŠ” μ„±λŠ₯에 영ν–₯을 μ£ΌκΈ° λ•Œλ¬Έμ—, λžŒλ‹€μ‹ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄μ•Ό 더 μ’‹λ‹€λŠ” λ‚΄μš©μ΄λ‹€.

Decompileν•΄μ„œ 확인해보면, ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λŠ” 것이 μ•„λ‹Œ, λ‚΄μš©μ΄ mainν•¨μˆ˜ 내에 λ³΅μ‚¬λ˜μ–΄ λ“€μ–΄κ°€ μžˆλ‹€!

μΈμžκ°€ ν•˜λ‚˜μΌ 경우 단좕 κ°€λŠ₯!
=> it μ‚¬μš©

shortFunc(5 ){println("a: $it")}

μ–˜λ„ κ°€λŠ₯!!!!

4. 읡λͺ…ν•¨μˆ˜, 인라인 ν•¨μˆ˜(2)

-인라인 ν•¨μˆ˜μ˜ μ œν•œκ³Ό κΈˆμ§€

-인라인 ν•¨μˆ˜μ˜ 단점
: μ½”λ“œκ°€ λ³΅μ‚¬λ˜λ―€λ‘œ λ‚΄μš©μ΄ λ§Žμ€ ν•¨μˆ˜μ— μ‚¬μš©ν•˜λ©΄ μ½”λ“œκ°€ λŠ˜μ–΄λ‚œλ‹€.

-noinline ν‚€μ›Œλ“œ
: 일뢀 λžŒλ‹€μ‹ ν•¨μˆ˜λ₯Ό 인라인 λ˜μ§€ μ•Šκ²Œ ν•˜κΈ° μœ„ν•΄

inline fun sub(out1: () -> Unit, noinline out2: () -> Unit){
//out2λŠ” λ³΅μ‚¬λ˜λŠ”κ²Œ μ•„λ‹ˆλΌ κ·ΈλŒ€λ‘œ λ‚¨μ•„μžˆμŒ

//====================================

inline fun shortFunc(a: Int, noinline b: (Int)->Unit){
//λ°˜ν™˜κ°’μ΄ μ—†λŠ” λžŒλ‹€μ‹ 인자 b
println("Hello")
b(a) //no inline
}
fun main(){
//shortFunc(5,{a -> println("a: $a")})
shortFunc(5 ){println("a: $it")}
}

Function1이 out.invokeλ₯Ό 톡해 aλ₯Ό ν˜ΈμΆœν•˜λŠ”λ°, mainν•¨μˆ˜μ—μ„œ 이가 κ·ΈλŒ€λ‘œ λ‚¨μ•„μžˆμŒ

//========================

-λΉ„μ§€μ—­λ°˜ν™˜

" μ½”ν‹€λ¦°μ—μ„œλŠ” 읡λͺ… ν•¨μˆ˜λ₯Ό μ’…λ£Œν•˜κΈ° μœ„ν•΄μ„œ return을 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λ•Œ νŠΉμ • λ°˜ν™˜κ°’ 없이 return만 μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€. κ·Έλ ‡λ‹€λ©΄ λžŒλ‹€μ‹ ν•¨μˆ˜λ₯Ό λΉ μ Έ λ‚˜μ˜€λ €λ©΄ μ–΄λ–»κ²Œ ν• κΉŒμš”? λžŒλ‹€μ‹ ν•¨μˆ˜λ₯Ό 인자둜 μ‚¬μš©ν•˜λŠ” ν•¨μˆ˜λŠ” μ˜λ„ν•˜μ§€ μ•Šκ²Œ λžŒλ‹€μ‹ ν•¨μˆ˜ λ°”κΉ₯에 μžˆλŠ” ν•¨μˆ˜κ°€ 같이 λ°˜ν™˜λ˜ λ²„λ¦¬λŠ”λ° 이것을 비지역 λ°˜ν™˜μ΄λΌκ³  ν•©λ‹ˆλ‹€. "

mainν•¨μˆ˜μ—μ„œ shortFunc 리턴을 μ£Όλ©΄, ν•΄λ‹Ή b만 λΉ μ Έλ‚˜κ°€λŠ” 것이 μ•„λ‹Œ, b와 shortFunc λͺ¨λ‘ λΉ μ Έλ‚˜κ°€κ²Œ λ˜μ–΄μ„œ 밑에 Goodbyeκ°€ 좜λ ₯이 μ•ˆλœλ‹€.

μ΄λ•Œ 이런 비지역 λ°˜ν™˜μ„ κΈˆμ§€ν•˜λ €λ©΄ crossinlineμ΄λΌλŠ” ν‚€μ›Œλ“œλ₯Ό λžŒλ‹€μ‹ ν•¨μˆ˜ μ•žμ— μ‚¬μš©ν•΄ ν•¨μˆ˜μ˜ λ³Έλ¬Έ λΈ”λ‘μ—μ„œ return이 μ‚¬μš©λ˜λŠ” 것을 κΈˆμ§€ν•  수 μžˆμŠ΅λ‹ˆλ‹€. crossinline ν‚€μ›Œλ“œλŠ” 비지역 λ°˜ν™˜μ„ κΈˆμ§€ν•΄μ•Ό ν•˜λŠ” λžŒλ‹€μ‹μ— μ‚¬μš©ν•©λ‹ˆλ‹€.

=> return을 μ‚¬μš©ν•  수 μ—†κ²Œ λœλ‹€.

5. ν™•μž₯ ν•¨μˆ˜

-ν™•μž₯ ν•¨μˆ˜(extension function)
:클래슀의 멀버 ν•¨μˆ˜λ₯Ό μ™ΈλΆ€μ—μ„œ 더 μΆ”κ°€ν•  수 μžˆλ‹€.

fun ν™•μž₯ λŒ€μƒ.ν•¨μˆ˜λͺ…(λ§€κ°œλ³€μˆ˜, ...): λ°˜ν™˜κ°’ {
...
return κ°’
}

ν΄λž˜μŠ€μ—λŠ” λ‹€μ–‘ν•œ ν•¨μˆ˜κ°€ μ •μ˜λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. 이것은 클래슀의 멀버 λ©”μ„œλ“œλΌκ³ λ„ λΆˆλ¦½λ‹ˆλ‹€. 그런데 κΈ°μ‘΄ 멀버 λ©”μ„œλ“œλŠ” μ•„λ‹ˆμ§€λ§Œ λ‚΄κ°€ μ›ν•˜λŠ” ν•¨μˆ˜λ₯Ό ν•˜λ‚˜ 더 ν¬ν•¨μ‹œμΌœ ν™•μž₯ν•˜κ³  싢을 λ•Œκ°€ μžˆμ„ κ²ƒμž…λ‹ˆλ‹€. μ½”ν‹€λ¦°μ—μ„œλŠ” 이처럼 클래슀처럼 ν•„μš”λ‘œ ν•˜λŠ” λŒ€μƒμ— ν•¨μˆ˜λ₯Ό 더 μΆ”κ°€ν•  수 μžˆλŠ” ν™•μž₯ ν•¨μˆ˜(extension function)λΌλŠ” κ°œλ…μ„ μ œκ³΅ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.


ν™•μž₯ ν•¨μˆ˜λ₯Ό λ§Œλ“€ λ•Œ 만일 ν™•μž₯ν•˜λ €λŠ” λŒ€μƒμ— λ™μΌν•œ μ΄λ¦„μ˜ 멀버 ν•¨μˆ˜ ν˜Ήμ€ λ©”μ„œλ“œκ°€ μ‘΄μž¬ν•œλ‹€λ©΄ 항상 ν™•μž₯ ν•¨μˆ˜λ³΄λ‹€ 멀버 λ©”μ„œλ“œκ°€ μš°μ„ μœΌλ‘œ ν˜ΈμΆœλ©λ‹ˆλ‹€.

**ν™•μž₯ν•¨μˆ˜ λΆ€λΆ„ 책보고 λ‹€μ‹œ κ³΅λΆ€ν•˜κΈ°

6. μ€‘μœ„ ν•¨μˆ˜

-μ€‘μœ„ ν‘œν˜„λ²•: 클래슀의 멀버 호좜 μ‹œ μ‚¬μš©ν•˜λŠ” 점(.)을 μƒλž΅ν•˜κ³  ν•¨μˆ˜ 이름 뒀에 μ†Œκ΄„ν˜Έλ₯Ό μƒλž΅ν•΄ 직관적인 이름을 μ‚¬μš©ν•  수 μžˆλŠ” ν‘œν˜„λ²•

-쑰건

  • 멀버 λ©”μ„œλ“œ / ν™•μž₯ ν•¨μˆ˜μ—¬μ•Ό ν•œλ‹€.
  • infix ν‚€μ›Œλ“œ μ‚¬μš©.
  • ν•˜λ‚˜μ˜ λ§€κ°œλ³€μˆ˜λ₯Ό κ°€μ Έμ•Ό ν•œλ‹€.
  • μ€‘μœ„ ν•¨μˆ˜λ₯Ό μ΄μš©ν•΄ μ—°μ‚°μžμ²˜λŸΌ μ‚¬μš©ν•˜κΈ°

    //μ€‘μœ„ ν‘œν˜„λ²•
    val multi_infix = 3 multiply 10
    println("multi_infix: $multi_infix")

val str1 = num.strPlus("Kotlin")//일반 ν‘œν˜„λ²•
val str2 = num strPlus "Kotlin"//μ€‘μœ„ ν‘œν˜„λ²•

7. μž¬κ·€ ν•¨μˆ˜

-자기 μžμ‹ μ„ λ‹€μ‹œ μ°Έμ‘°
-계속 ν˜ΈμΆœν•˜λŠ” νŠΉμ§•

-쑰건

  • λ¬΄ν•œ ν˜ΈμΆœμ— 빠지지 μ•Šλ„λ‘ νƒˆμΆœ 쑰건을 λ§Œλ“€μ–΄μ€€λ‹€.
  • μŠ€νƒ μ˜μ—­μ„ μ΄μš©ν•˜λ―€λ‘œ 호좜 횟수λ₯Ό λ¬΄λ¦¬ν•˜κ²Œ 많이 지정해 μ—°μ‚°ν•˜μ§€ μ•ŠλŠ”λ‹€.
  • μ½”λ“œλ₯Ό λ³΅μž‘ν•˜μ§€ μ•Šκ²Œ ν•œλ‹€.

+ 꼬리 μž¬κ·€ ν•¨μˆ˜(tail recursive func)

-μŠ€νƒμ— 계속 μŒ“μ΄λŠ” 방식이 ν•¨μˆ˜κ°€ 계속 μ”Œμ›Œμ§€λŠ” 꼬리λ₯Ό λ¬΄λŠ” ν˜•νƒœ
-tailrec ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•΄ μ„ μ–Έ

fun main(){
    val num = 5
    println("Factorial : $num -> ${factorial(num)}")
}

tailrec fun factorial(n:Int, run: Int = 1): Long{
    return if(n==1) run.toLong() else **factorial(n-1, run*n)**
}

=> μŠ€νƒ 곡간을 λ‚­λΉ„ν•˜μ§€ μ•Šμ•„λ„ λ˜λ―€λ‘œ, 일반 μž¬κ·€ν•¨μˆ˜λ³΄λ‹€ 훨씬 μ•ˆμ „ν•œ μ½”λ“œκ°€ λœλ‹€.

8. ν•¨μˆ˜μ˜ μ‹€ν–‰ 블둝

-ν•¨μˆ˜μ˜ 블둝({})
: 지역 λ³€μˆ˜
<-> μ „μ—­ λ³€μˆ˜

-ν•¨μˆ˜μ˜ λ²”μœ„
1) μ΅œμƒμœ„ ν•¨μˆ˜, 지역 ν•¨μˆ˜

fun main() { // μ΅œμƒμœ„ 레벨의 ν•¨μˆ˜
    ...
    fun secondFunc(a: Int) { // 지역 ν•¨μˆ˜ μ„ μ–Έ
        ... 
    }
    userFunc(4) // μ‚¬μš©μž ν•¨μˆ˜ μ‚¬μš© - **μ„ μ–ΈλΆ€μ˜ μœ„μΉ˜μ— 상관 없이 μ‚¬μš©**
    secondFunc(2) // 지역 ν•¨μˆ˜ μ‚¬μš© - **μ„ μ–ΈλΆ€κ°€ λ¨Όμ € λ‚˜μ™€μ•Ό μ‚¬μš© κ°€λŠ₯**
}

fun userFunc(counts: Int) { // μ‚¬μš©μžκ°€ λ§Œλ“  μ΅œμƒμœ„ 레벨의 ν•¨μˆ˜ μ„ μ–Έ
    ...
}
profile
Major interest in iOS πŸ€ & 🍎

0개의 λŒ“κΈ€