코틀린에서 함수는 일급객체입니다. 따라서 파라미터로 함수를 받거나 변수에 함수를 저장하는 등의 작업이 가능합니다

 

문법

val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }

# 생략 ver
val sum = { x: Int, y: Int -> x + y }           # 1
val sum: (Int, Int) -> Int = { x, y -> x + y }  # 2 (비추)
  • 람다의 본문은 항상 중괄호({, })로 둘러싸여 있음
  • 파라미터 타입은 람다 내 파라미터 부분 또는 람다 할당하는 변수 타입 둘중 한군데만 쓰면 되는데, 위 예제에서 1번처럼 쓰는걸 추천
  • 화살표(->) 뒤에 본문이 나온옴
  • 추론된 람다 리턴타입이 Unit(자바 void랑 비슷)이 아니라면, 람다 본문의 마지막 expression이 리턴타입이 됨
    (람다 본문에는 return을 사용할 수 없음)

 

Trailing lambda

함수의 마지막 파라미터가 함수타입이라면 괄호 밖에 람다식을 쓸 수 있습니다.

 

fun <T, R> Collection<T>.fold(
    initial: R,
    combine: (acc: R, nextElement: T) -> R
): R {
    // ...
}

위처럼 fold라는 확장함수가 있다고 했을 때

 

val items = listOf(1, 2, 3, 4, 5)
// val product = items.fold(1, { acc, e -> acc * e })
val product = items.fold(1) { acc, e -> acc * e }  // preferred!

이런식으로 쓰는게 권장됩니다. 안 써도 동일하게 동작은 하는데 이게 코틀린 스타일이라고 하네요

 

run { println("...") }

만약 파라미터가 람다 하나뿐이라면 괄호도 생략 가능합니다

 

it

ints.filter { it > 0 } // this literal is of type '(it: Int) -> Boolean'

람다 파라미터가 한개이면서 타입을 추론할 수 있는 경우, 파라미터 선언부와 화살표(->)를 생략하고 it을 파라미터로 사용 가능합니다

 

언더스코어(_)

map.forEach { (_, value) -> println("$value!") }
// _는 사용 불가 ex) println(_) -> 안됨

람다 파라미터가 사용되지 않으면 언더스코어(_)로 대체할 수 있습니다.

코틀린에서 언더스코어는 예약어이기 때문에 일반적으로 변수명 등으로 사용할 수는 없습니다

 

파이썬에도 비슷한 용례가 있긴 한데 파이썬에서는 사실 _라는 변수를 만드는거라 코틀린과는 동작방식에 차이가 있습니다.

파이썬 쓰다보면 종종 _가 겹치는 문제가 발생하는데(ex. django에서 from ... import ugettext_lazy as _) 그런 점에서 코틀린 방식이 더 나은거같네요

 

클로저(closure)

var sum = 0
ints.filter { it > 0 }.forEach {
    sum += it
}
print(sum)

람다 내부에서 외부 변수(=captured variables)에 접근할 수 있습니다.

 

주의사항

- 람다가 이벤트 핸들러 등 비동기적으로 실행되는 함수로 사용된다면, 로컬변수에 대한 수정은 항상 람다가 실행된 후에 반영된다는 점을 명심하세요

fun tryToCountButtonClicks(button: Button): Int {
    var clicks = 0
    button.onClick { clicks++ }
    return clicks
}

예를 들어 이런 함수는 항상 0을 반환할겁니다

 

- 람다가 어떻게 동작하는지 명확히 알아야 합니다

people.filter { it.age == people.maxBy(Person::age)!!.age }

예를 들어 위와 같은 코드는 사람 수만큼 최댓값을 구하는 연산을 반복합니다

val maxAge = peopel.maxBy(Person::age)!!.age
people.filter { it.age == maxAge }

따라서 이런식으로 바꿔줘야 합니다.

 

Reference

- https://kotlinlang.org/docs/lambdas.html

반응형

'프로그래밍 > Kotlin' 카테고리의 다른 글

[Kotlin] groupBy  (0) 2022.04.02
[Kotlin] count, size 함수 (kotlin in action)  (0) 2022.04.02
[Kotlin] Delegation (위임)  (0) 2022.03.27
[Kotlin] local function (로컬 함수)  (0) 2022.03.26
[Kotlin] infix call (중위 호출)  (0) 2022.03.26