Kotlin DSL을 대충 이해한 채로 사용하다가 제대로 이해해 보려던 중 Lambda부터 한번 정리해야겠다 싶었다.
언어별로 람다를 사용해서 간단한 함수를 만들어 봤어요.
(두 개의 정수를 더한 결과를 반환하는 sum
함수)
TypeScript
const sum = (a: number, b: number) => a + b;
sum(2, 5);
Python
sum = lambda a, b : a + b
sum(2, 5)
C#
Func<int, int, int> sum = (a, b) => a + b;
sum(2, 5);
Java
BiFunction<Integer, Integer, Integer> sum = (a, b) -> a + b;
sum.apply(2, 5);
그리고
Kotlin
val sum = { a: Int, b: Int -> a + b }
sum(2, 5)
다 비슷비슷하네요.
그럼,
람다란 함수를 간략하게 정의할 수 있는 수단인가?
틀린 말은 아닌데..
더 중요한 건 지금부터에요.
"Kotlin functions are first-class"
함수 parameter의 argument로 Int
, String
과 같은 값뿐만 아니라 함수를 전달할 수도 있어요.
(함수를 전달받는 함수를 high-order function이라고 함)
fun higherOrderFunction(functionTypeParam: (Int, Int) -> Int) {}
함수를 전달받을 수 있는 high-order function을 하나 만들었어요.
parameter는 두 개의 Int
를 받고 Int
를 반환하는 함수에요.
parameter 타입이 아까 위에서 만들었던 sum()
함수의 타입과 같아서 sum
함수를 전달할 수 있을 것 같네요. 전달해 보겠습니다.
val sum = { a: Int, b: Int -> a + b }
higherOrderFunction(functionTypeParam = sum)
(참고로, 코틀린에서는 sum
함수를 fun
키워드를 사용하여 정의했다면 위처럼 전달 불가)
여기까지만으로도 문법적 오류 없이 함수를 잘 전달했어요.
그렇지만 가독성을 해치지 않는 선에서 간결하게 표현할수록 더 좋지 않을까요?
위에서 보았던 sum()
함수를 전달하며 higherOrderFunction()
함수를 호출하는 구문을 간략하게 만들어 가 보겠습니다.
+1 강화!
중간 역할을 하는 sum
이라는 변수를 없애면서 좀 더 간략하게.
higherOrderFunction(functionTypeParam = { a: Int, b: Int -> a + b })
+2 강화!
이 경우, a
, b
의 타입을 추론할 수 있기 때문에 아래와 같이 타입을 명시한 부분(: Int
)을 생략할 수 있어요.
higherOrderFunction(functionTypeParam = { a, b -> a + b })
+3 강화!
이제, parameter 이름을 명시한 부분도 생략해 봅시다.
higherOrderFunction({ a: Int, b: Int -> a + b })
+4 강화!
마지막으로, 괄호()
마저 생략할 수 있어요.
higherOrderFunction { a: Int, b: Int -> a + b }
마지막 형태만 딱 놓고 보면 좀 헷갈릴 수도 있을 텐데,
우린 방금까지 higherOrderFunction()
이라는 함수에게 '두 Int
를 받아 그 합을 반환하는 함수'를 전달한 거에요.
(사실 이 마지막 형태 때문에 이 글을 작성하게 된 것이랍니다.)
이렇듯 람다를 이용하면 간결하게 함수에게 함수를 전달할 수 있어요.
(또한, Kotlin DSL로 확장)
핵심적인 건 다 끝났고
자잘한 것들만 코드로 간단하게 살펴 봅시다.
val sum = { a: Int, b: Int ->
println("a: $a")
println("b: $b")
// 마지막 줄에 있으면 return 키워드 없이 return됨
a + b
}
fun higherOrderFunction(s: String, functionTypeParam: (Int, Int) -> Int) {}
// higherOrderFunction("두 정수의 합", { a, b -> a + b })
higherOrderFunction("두 정수의 합") { a, b -> a + b } // 소괄호 바깥에 람다
fun higherOrderFunction(functionTypeParam: (Int, Int) -> Int, s: String) {}
higherOrderFunction({ a, b -> a + b }, "두 정수의 합") // 소괄호 안에 람다
fun higherOrderFunction(functionTypeParam: (Int) -> Int) {}
higherOrderFunction { num -> num * num }
higherOrderFunction { it * it }
higherOrderFunction()
에게 '정수 하나를 받아 그 제곱을 반환하는 함수'를 전달한 것