[Kotlin] ๋๋ค(Lambda) ํํ์
#1 ๋๋ค ๋์์ ๋๋ค ํํ์
#1-1 ๋๋ค ๋์
// ์ํ - ํจ์์ ํํ
f(x) = x + 1
g(x, y) = x * y + 1
// ์ํ - ๋๋ค ๋์๋ก ํจ์ ํํ
λx. x + 1
λx. λy. x * y + 1
ํ๋ก๊ทธ๋๋ฐ์์์ ๋๋ค ํํ์(Lambda Expression)์ ์ํ์์์ ๋๋ค(λ) ๋์(Lambda Calculus)์์ ๋น๋กฏ๋ ๊ฐ๋ ์ด๋ค. ๋๋ค ๋์๋ ํจ์์ f๋ g์ ๊ฐ์ ์ด๋ฆ์ ๋ถ์ด์ง ์๋๋ค. ํจ์์ ๋ชธํต ์ฆ, ๊ณ์ฐ ๋ถ๋ถ๋ง์ ๋จ์ํ๊ฒ ํํํ๋ค.
#1-2 ๋๋ค ํํ์
// ์ฝํ๋ฆฐ - ํจ์์ ํํ
fun f(x: Int): Int {
return x + 1
}
fun g(x: Int, y: Int): Int {
return x * y + 1
}
// ์ฝํ๋ฆฐ - ๋๋ค ํํ์์ผ๋ก ํจ์ ํํ
{ x: Int -> x + 1 }
{ x: Int, y: Int -> x * y + 1 }
ํ์ง๋ง, ๋๋ค ๋์์์ ํจ์๋ฅผ ํํํ ๋ ์ฌ์ฉํ๋ ๋๋ค(λ) ๊ธฐํธ๋ฅผ ํ๋ก๊ทธ๋๋ฐ์์๋ "->"(๋๋ถ๋ถ์ ๊ฒฝ์ฐ) ๋๋ "lambda"(ํ์ด์ฌ ๋ฑ์ ๊ฒฝ์ฐ)๋ก ๋ฐ๊ฟ ํํํ๋ค. ์ฆ, ํ๋ก๊ทธ๋๋ฐ์์์ ๋๋ค ํํ์์ ๋๋ค์๋ ๋๋ค์์ด๋ค. ์๋ฅผ ๋ค์ด, f(x) = x + 1 ๋ผ๋ ํจ์๋ฅผ ๋๋ค ๋์์์๋ λx. x + 1 ๋ก ํํํ๊ณ ์ฝํ๋ฆฐ์์ x -> x + 1๋ก ํํํ๋ค.
๋, ๋๋ค ํํ์์ผ๋ก ํํํ ์ฝํ๋ฆฐ ํจ์๋ f๋ g๊ฐ์ ํจ์์ ์ด๋ฆ์ด ์์์ ๋ณผ ์ ์๋ค. ๋๋ค ๋์์ ์ทจ์ง๋๋ก, ํจ์์ ์ด๋ฆ์์ด ํํํ๋ค. ํ์ง๋ง, ์ฌ๋ฏธ์๊ฒ๋ ์ด๋ฌํ ๋๋ค ํํ์ ํจ์์ ์ด๋ฆ์ ๋ถ์ผ ์๋ ์๋ค.
#1-3 ์ด๋ฆ์ด ๋ถ์ ๋๋ค ํํ์
// ์ฝํ๋ฆฐ - ์ด๋ฆ์ด ๋ถ์ ๋๋ค ํํ์
val f: (Int) -> Int = { x: Int -> x + 1 }
val g: (Int, Int) -> Int = { x: Int, y: Int -> x * y + 1 }
์ ์ด๋ฐ ์ง์ ํ๋๋ฉด, ๋๋ค ํํ์์ (์ฒ์ ๋ฐฐ์ฐ๊ธฐ์ ์ด๋ ต์ง๋ง) ๊ฐ๊ฒฐํ ๋ฌธ๋ฒ์ ์ทจํ๋ฉด์ ๋์์ (์ด๋ฆ์ ๋ถ์์ผ๋ก์จ) ํด๋น ํจ์๋ฅผ ์ฌ์ฌ์ฉํ ์ ์๋ค๋ ์ด์ ์ด ์๊ธฐ ๋๋ฌธ์ด๋ค.
์์ ์ฝ๋์ ์๋ (Int) -> Int ๋ฐ (Int, Int) -> Int๋ ๋๋ค ํํ์์ด ์๋์ ์ ์ํ๋ค. ํด๋น ํํ์์ ์ฝํ๋ฆฐ์ ํจ์ ํ์ (Function Type) ํํ์์ผ๋ก ์ด๋ค ํจ์๊ฐ ๊ฐ์ง๋ ๋งค๊ฐ๋ณ์์ ํ์ ๊ณผ ๋ฐํ ํ์ ์ ์ ์ํ๋ ํํ์์ด๋ค. ํ์ดํ(->)๊ฐ ์๋ค๊ณ ๋ค ๋๋ค ํํ์์ธ๊ฒ ์๋๋ค.
#1-4 ํ์ ์๋ต
// ํ์ ์๋ต - ํจ์ ํ์ ํํ์์ ์๋ต
val f = { x: Int -> x + 1 }
val g = { x: Int, y: Int -> x * y + 1 }
// ํ์ ์๋ต - ๋๋ค ํํ์ ๋ด๋ถ์ ๋งค๊ฐ๋ณ์ ํ์ ์ ์๋ต
val f: (Int) -> Int = { x -> x + 1 }
val g: (Int, Int) -> Int = { x, y -> x * y + 1 }
// ํ์ ์๋ต - ๋ ๋ค ์๋ต (#2-3 ์ฐธ์กฐ)
val f = { println("ํ๋ค๋ฆฌ๋ ๊ฝ๋ค ์์์ ๋ค ์ดํธํฅ์ด ๋๊ปด์ง๊ฑฐ์ผ") }
#1-3์ ์ฝ๋์์, ์ฝํ๋ฆฐ์ด ์ง์ํ๋ ํ์ ์ถ๋ก ์ ์๊ฑฐํด ์ฝ๋์ ์ผ๋ถ๋ถ์ ์๋ตํ ์๋ ์๋ค. ๋จ ํ๊ฐ์ง ๊ฒฝ์ฐ(#2-3 ์ฐธ์กฐ)๋ฅผ ์ ์ธํ๊ณ , ํจ์ ํ์ ํํ์๊ณผ ๋๋ค ํํ์ ๋ด๋ถ์ ๋งค๊ฐ๋ณ์ ํ์ ๋ ๋ค๋ฅผ ์๋ตํ ์๋ ์๋ค. ์ฝํ๋ฆฐ์ ์ปดํ์ผ๋ฌ ์ ์ฅ์์ ํ์ ์ถ๋ก ์ด ๋ถ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ด๋ค.
#2 ๋ค์ํ ์ํฉ์์์ ๋๋ค ํํ์ ๋ฌธ๋ฒ
#2-1 ๋งค๊ฐ๋ณ์๊ฐ ์๋ ๊ฒฝ์ฐ์ ํํ
// ๊ธฐ๋ณธ (ํ์ ์๋ต ์ ํจ)
val noParameterLambda: () -> String = { () ->"Hello, World!"}// ํ์ ์๋ต - ํจ์ ํ์ ํํ์์ ์๋ตval noParameterLambda = { () ->"Hello, World!"}
// ํ์ ์๋ต - ๋๋ค ํํ์ ๋ด๋ถ์ ๋งค๊ฐ๋ณ์ ํ์ ์ ์๋ต
val noParameterLambda: () -> String = {
"Hello, World!"
}
๋งค๊ฐ๋ณ์๊ฐ ์๋ค๋ฉด ()์ ๊ฐ์ด ํจ์ ํ์ ํํ์์ ๊ดํธ ์์ ์๋ฌด๊ฒ๋ ๋ฃ์ง ์์ผ๋ฉด ๋๋ค. ๊ทธ๋ฌ๋, ์ด๋ ํจ์ ํ์ ํํ์์์๋ง ๊ฐ๋ฅํ๊ณ ๋๋ค ํํ์ ๋ด๋ถ์ ๋งค๊ฐ๋ณ์ ํ์ ๋ถ๋ถ์์ ๋ฌธ๋ฒ์ ๋ถ๊ฐ๋ฅํ๋ค. ๊ฐ๋ฅํ๊ฒ ๋ง๋ค์ด์ค๋ ๊ด์ฐฎ์ ๊ฒ ๊ฐ์๋ฐ ์ ๋ง์๋จ๋์ง ์๋ฌธ์ด ๋ ๋ค. ์๋ฌดํผ, ๋งค๊ฐ๋ณ์๊ฐ ์๋ ๊ฒฝ์ฐ ๋ฐ๋์ ๋๋ค ํํ์ ๋ด๋ถ์ ๋งค๊ฐ๋ณ์ ํ์ ์ด ์๋ต๋ ํํ๋ก๋ง ํจ์๋ฅผ ์งค ์ ์๋ค.
#2-2 return์ ํ์ง ์๋ ๊ฒฝ์ฐ (์๋ฐ๋ก ์น๋ฉด, ๋ฆฌํด ํ์ ์ด void)์ ํํ
// ๊ธฐ๋ณธ (ํ์ ์๋ต ์ ํจ)
val noReturnTypeLambda: (Int, String) -> Unit = { number: Int, text: String ->
println("Received number: $number and text: $text")
}
// ํ์ ์๋ต -ํจ์ ํ์ ํํ์์ ์๋ต (์๋ฌ๊ฐ ๋์ง ์์ง๋ง, ์ฌ์ฉ์ ์ง์ํ์.)
val noReturnTypeLambda = { number: Int, text: String ->
println("Received number: $number and text: $text")
}
// ํ์ ์๋ต - ๋๋ค ํํ์ ๋ด๋ถ์ ๋งค๊ฐ๋ณ์ ํ์ ์ ์๋ต
val noReturnTypeLambda: (Int, String) -> Unit = { number, text ->
println("Received number: $number and text: $text")
}
ํจ์ ํ์ ํํ์์์ ํจ์์ return์ด ์๋ ๊ฒฝ์ฐ return ํ์ ์๋ฆฌ์ Unit์ ๋ฃ๋๋ค. Unit์ ์๋ฐ์ void์ ๋์๋๋ ํค์๋๋ค. return์ด ์๋ ํจ์์์ ํจ์ ํ์ ํํ์์ ์๋ตํ๋ฉด ์ฝํ๋ฆฐ์ ์ปดํ์ผ๋ฌ๊ฐ ํ์ ์ถ๋ก ์ ํตํด return ํ์ ์ ์ ํ๋ค. ํ์ง๋ง ์ฌ๋งํด์๋ ํจ์ ํ์ ํํ์์ ์๋ตํ์ง ๋ง์.
์๋ตํ๋ค๊ณ ์๋ฌ๊ฐ ๋๋ ๊ฑด ์๋๋ค. ์ค๊ฐ์ ์๋ ์ฝ๋๋ฅผ ๋ณต์ฌํด์ ์ฝํ๋ฆฐ IDE์ ๋ถ์ฌ๋์ผ๋ฉด ์ ์๋ํ๋ ๋ชจ์ต์ ๋ณผ ์ ์๋ค. ํ์ง๋ง, ํด๋น ์ฝ๋๋ ํ๋ก๊ทธ๋๋จธ์ ํต์ ๋ฅผ ๋ฒ์ด๋ ์ฝ๋๋ค. ์๋ฅผ ๋ค์ด, ์ด๋ค ํ๋ก๊ทธ๋๋จธ๊ฐ return ํ์ ์ด ์๋ ํจ์๋ฅผ ๋ง๋ค๊ธฐ๋ก ๋ง์๋จน์์ผ๋, ์ด์ฉ๋ค ์ค์๋ก ์ค๊ดํธ ๋์ { ... "์๋ฌด๋ง" }์ ๊ฐ์ด String ๊ฐ์ฒด๋ฅผ ๋ฐฐ์นํ๋ฉด ํ์ ์ถ๋ก ์ ์ํด ํด๋น ํจ์์ return ํ์ ์ String์ด ๋์ด๋ฒ๋ฆฐ๋ค. ํจ์ ํ์ ํํ์์ ํตํด ์ป์ ์ ์๋ return ํ์ ์ ๋ช ์์ฑ์ ์ด์ฉํ๋ ํ๋ก๊ทธ๋๋จธ๊ฐ ๋์.
#2-3 ๋งค๊ฐ๋ณ์๋ ์๊ณ return๋ ํ์ง ์๋ ๊ฒฝ์ฐ์ ํํ
// ๊ธฐ๋ณธ (ํ์ ์๋ต ์ ํจ)
val noParaNoReturn: () -> Unit = { () ->println("This is a lambda with no parameters and no return type.")}// ํ์ ์๋ต - ํจ์ ํ์ ํํ์์ ์๋ตval noParaNoReturn = { () ->println("This is a lambda with no parameters and no return type.")}
// ํ์ ์๋ต - ๋๋ค ํํ์ ๋ด๋ถ์ ๋งค๊ฐ๋ณ์ ํ์ ์ ์๋ต
val noParaNoReturn: () -> Unit = {
println("This is a lambda with no parameters and no return type.")
}
---
// ํ์ ์๋ต - ๋ ๋ค ์๋ต
val noParaNoReturn = {
println("ํ๋ค๋ฆฌ๋ ๊ฝ๋ค ์์์ ๋ค ์ดํธํฅ์ด ๋๊ปด์ง๊ฑฐ์ผ")
}
#2-1๊ณผ #2-2์ ๊ต์งํฉ์, ๋๋ค ํํ์ ๋ด๋ถ์ ๋งค๊ฐ๋ณ์ ํ์ ์ด ์๋ต๋ ํํ๋ค. ๋ฐ๋ผ์, ํด๋น ํํ๋ก๋ง ํจ์๋ฅผ ์งค ์ ์๋ค. ์ถ๊ฐ๋ก, ๋งค๊ฐ๋ณ์์ ๋ฆฌํด์ด ๋๋ค ์๋ ๊ฒฝ์ฐ์๋ ํจ์ ํ์ ํํ์๊ณผ ๋๋ค ํํ์ ๋ด๋ถ์ ๋งค๊ฐ๋ณ์ ํ์ ์ ๋ ๋ค ์๋ตํ ์ ์๋ค. ์ด ๋๋ ํ์ดํ(->)๋ง์ ์๋ตํ๋ค. ์ด๋ ๋ ๋ค ์๋ตํ ์ ์๋ ๋จ ํ ๊ฐ์ง์ ํน๋ณ ์ผ์ด์ค๋ค. ๊ทธ๋ฆฌ๊ณ ์ด ํน๋ณ ์ผ์ด์ค์ ์กด์ฌ ๋๋ฌธ์ ๋๋ค์์ ๋ฐ๋์ ํ์ดํ(->)๋ฅผ ๊ฐ์ง๋ค๊ณ ๋งํ ์ ์๊ฒ ๋๋ค.
#2-4 it ํค์๋ (๋งค๊ฐ๋ณ์๊ฐ ํ๋์ธ ๊ฒฝ์ฐ)
// ํ๋ฒํ ๋๋ค ํํ์
val f: (Int) -> Int = { x: Int -> x + 1 }
// it์ ์ฌ์ฉํ ๋๋ค ํํ์
val f: (Int) -> Int = { it + 1 }
it(๊ทธ๊ฑฐ)๋ผ๋ ํค์๋๋ก ํด๋น ๋งค๊ฐ๋ณ์๋ฅผ ํํํ ์ ์๋ค. ๋งค๊ฐ๋ณ์๊ฐ ํ๋์ผ ๋๋ง it ํค์๋๋ฅผ ์ฌ์ฉํ ์ ์๋ค. it์ ์ฌ์ฉํ ์ ์๋ ์ํฉ์ด๋ฉด, ์ค๊ดํธ { ... } ๋ด๋ถ์์ ํ์ดํ์ ๊ทธ ์ผ์ชฝ ๋ถ๋ถ์ ์๋ตํด๋ ์๋ฌ๊ฐ ๋ฐ์ํ์ง ์๋๋ค.
#2-5 ์๊ดํธ ์๋ต (์ธ์๋ก ์ฐ์ธ ๋๋ค ํํ์์ด ๋ง์ง๋ง ์ธ์์ธ ๊ฒฝ์ฐ)
class calculator(
val args1: Int,
val args2: Int,
val args3: (Int, Int) -> Int
) {
fun additionOperation(): Int {
return args1 + args2
}
fun differenceOperation(): Int {
return Math.abs(args1 - args2)
}
fun customOperation(): Int {
return args3(args1, args2)
}
}
fun main() {
val myCalculator1 = calculator(3, 4, {x, y -> (x * x) + y}) // ๋๋ค ํํ์์ด ์๊ดํธ ์์ ์์
val myCalculator2 = calculator(3, 4) {x, y -> (x * x) + y} // ๋๋ค ํํ์์ด ์๊ดํธ ๋ฐ์ ์์
println(myCalculator1.customOperation()) // ์ถ๋ ฅ ๊ฒฐ๊ณผ: 13
println(myCalculator2.customOperation()) // ์ถ๋ ฅ ๊ฒฐ๊ณผ: 13
}
์ฝํ๋ฆฐ์์ ์ด์ ๊ฐ์ด ๋๋ค ํจ์๋ฅผ ์ธ์๋ก์ ์ ๋ฌํ ์ ์๋ค. ์ด ๋, ๋๋ค ํํ์์ด ๋ง์ง๋ง ์ธ์๋ก ์ฌ์ฉ๋๋ ๊ฒฝ์ฐ์๋ myCalculator2์์์ฒ๋ผ ์๊ดํธ์์ ๋นผ๊ณ ๊ทธ ์ค๋ฅธ์ชฝ์ ์ ์ด๋ ๋๋ค. ์ด๋ ๊ฐ๋ ์ฑ ํฅ์์ ์ํด ์ ๊ณต๋๋ ํธ์์ฑ ๋ฌธ๋ฒ์ด๋ค.
#3 ํจ์ํ ์ธํฐํ์ด์ค์ ๊ตฌํ
// SAM Conversions๋ ๋จ์ผ ์ถ์ ๋ฉ์๋ ์ธํฐํ์ด์ค
fun interface MyOperation {
fun operate(x: Int, y: Int): Int
}
fun main() {
val addition = MyOperation { x, y -> x + y }
val subtraction = MyOperation { x, y -> x - y }
val result1 = addition.operate(5, 3)
val result2 = subtraction.operate(5, 3)
println("Result of addition: $result1") // ์ถ๋ ฅ ๊ฒฐ๊ณผ: 8
println("Result of subtraction: $result2") // ์ถ๋ ฅ ๊ฒฐ๊ณผ: 2
}
fun ํค์๋์ ํจ๊ป ๋จ์ผ ์ถ์ ๋ฉ์๋๋ฅผ ๊ตฌํํ๋ ์ธํฐํ์ด์ค์ธ ํจ์ํ ์ธํฐํ์ด์ค๋ ๋๋ค ํํ์์ด ํ์ฉ๋๋ ๋ํ์ ์ธ ์ฌ์ฒ๋ค. ์ฝํ๋ฆฐ์ด ์ง์ํ๋ ๋ฌธ๋ฒ์ผ๋ก ๊ฐํธํ๊ฒ ๊ตฌํ ํด๋์ค๋ฅผ ๋ง๋ค ์ ์๋ค. ๊ทธ ๋ฌธ๋ฒ์ ๋ฐ๋ก ์ด๋ค ๋ณ์์, ์ธํฐํ์ด์ค ์ด๋ฆ + ๋๋ค ํํ์์ ํ ๋นํ๋ฉด ๋์ด๋ค. ์ด๋ฌ๋ฉด ๋๋จธ์ง๋ ์ฝํ๋ฆฐ ์ปดํ์ผ๋ฌ๊ฐ ์์์ ์์ ํ๋ค. ๊ทธ ์์ ์ ๋ฐ๋ก, ํด๋น ๋๋ค ํํ์ ํจ์๋ฅผ ์ธํฐํ์ด์ค์ ํ๋ ์๋ ๋ฉ์๋๋ก์ ์ค๋ฒ๋ผ์ด๋ํ๊ณ , ์ต๋ช ํด๋์ค๋ฅผ ๋ง๋๋ ๊ฒ์ด๋ค (์ฌ๊ธฐ์์ ๊ทธ ์ต๋ช ํด๋์ค๋ฅผ addition ๋ฐ subtraction์ ํ ๋นํจ์ผ๋ก์จ ์ด๋ฆ ์๋ ํด๋์ค๋ก ๋ง๋ค์๋ค). ํจ์ํ ์ธํฐํ์ด์ค์ ๋ํ ์์ธํ ๋ด์ฉ์ ๋ค์ ๊ฒ์๊ธ์์ ์ดํด๋ณผ ์ ์๋ค.
[Kotlin] ํจ์ํ ์ธํฐํ์ด์ค (Single Abstract Method Interface)
#1 ์ผ๋ฐ ์ธํฐํ์ด์ค #1-1 ํ๋ฒํ ์ธํฐํ์ด์ค interface MyNormalInterface { fun myFirstMethod(value: Int): String fun mySecondMethod(value1: Int, value2: String): Int ... } ์ฐ๋ฆฌ๊ฐ ์ ์๊ณ ์๋ ์ธํฐํ์ด์ค์ ๋ชจ์ต์ด๋ค. #1-2 ํจ์
kenel.tistory.com
#4 ์์ฝ
๋๋ค ํํ์์ ์ฒ์ ๋ฐฐ์ฐ๊ธฐ์ ๋ถ๋ช ์ด๋ ต์ง๋ง, ์ฐ๋ฉด ์ธ์๋ก ๊ทธ ๊ฐํธํจ์ ์ธ์ ํ๊ฒ ๋๋ค.