fun <T, R> Collection<T>.fold(
initial: R,
combine: (acc: R, nextElement: T) -> R
): R {
// ...
}
fold
함수를 호출하려면 함수 타입의 인스턴스를 전달해야 하는데 이 때 람다 표현식이 널리 사용된다.val joinedToString = items.fold("Elements:", { acc, i -> acc + " " + i })
(Int) → String
과 같은 함수 타입엔 특수 표기법이 존재한다.
(A, B) -> C
A.(B) → C
suspend
수식어를 통해 포함된다.
suspend () → Unit
{ a, b -> a + b }
.fun(s: String): Int { return s.toIntOrNull() ?: 0 }
::isOdd
, String::toInt
List::size
::Regex
foo::toString
class IntTransformer: (Int) -> Int {
override operator fun invoke(x: Int): Int = TODO()
}
val intFunction: (Int) -> Int = IntTransformer()
val a = { i: Int -> i + 1 } // (Int) -> Int로 추론
(A, B) -> C
타입의 값을 A.(B) -> C
타입 자리에 써도 되고, 그 반대도 가능하다.invoke
연산자 또는 바로 괄호를 통해 호출 가능하다.
f.invoke(x)
또는 f(x)
// max는 함수를 인자로 받기에 고차 함수
max(strings, { a, b -> a.length < b.length })
→
뒤에 온다.Unit
이 아닌 경우 람다 본문 내부의 마지막 표현식이 반환 값으로 처리된다.val sum = { x: Int, y: Int -> x + y }
run { println("...") }
→
를 생략하여 암시적으로 it
으로 매개변수를 표현할 수 있다.ints.filter { it > 0 } // '(it: Int) -> Boolean'
// 아래 두 표현은 같다
ints.filter {
val shouldFilter = it > 0
shouldFilter
}
ints.filter {
val shouldFilter = it > 0
return@filter shouldFilter
}
map.forEach { (_, value) -> println("$value!") }
val (name, age) = person
Pair
나 Map.Entry
등일 때 이러한 구조 분해를 이용할 수 있다.map.mapValues { (key, value) -> "$value!" }
fun(x: Int, y: Int): Int = x + y
fun(x: Int, y: Int): Int {
return x + y
}
return
은 람다를 감싸고 있는 외부 함수를 종료시킨다.return
은 해당 익명 함수만을 종료시키고 외부 함수에는 영향을 주지 않는다.// 람다식에서의 non-local return 예시
fun lambdaTest() {
listOf(1, 2, 3).forEach {
if (it == 2) return // lambdaTest 함수 전체를 종료시킴 (non-local return)
println(it)
}
println("이 문장은 출력되지 않음")
}
// 익명 함수에서의 return 예시
fun anonymousFuncTest() {
listOf(1, 2, 3).forEach(fun(value) {
if (value == 2) return // 익명 함수만 종료, forEach는 계속됨 (local return)
println(value)
})
println("이 문장은 정상적으로 출력됨")
}
var sum = 0
ints.filter { it > 0 }.forEach {
sum += it // 외부 sum 변수를 캡쳐
}
print(sum)
함수 리터럴이란 이름 없는 함수 표현 자체를 의미 (람다, 익명 함수)
A.(B) → C
this
참조로 사용할 수 있게 되는 것val sum: Int.(Int) -> Int = { other -> plus(other) } // this.plus(other)
val sum = fun Int.(other: Int): Int = this + other // 익명 함수로 표현하면 이와 같다.
class HTML {
fun body() { ... }
}
fun html(init: HTML.() -> Unit): HTML {
val html = HTML() // 리시버 객체 생성
html.init() // 파라미터로 전달 받은 Html을 리시버로 가지는 () -> Unit 호출
return html
}
html { // 리시버가 있는 람다 시작
body() // html 함수의 init의 매개변수로 body 전달 (Html 클래스의 () -> Unit 타입 멤버 함수)
}