함수 리터럴 (function literal) 이라고 부르기도 한다.식(expression) 으로, 반환(return) 값을 가질 수 있다.Unit (Java의 void와 비슷하다) 이라면 반환 값이 없다.val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y}
{ }안에 작성되는게 람다 식이다.
= 앞은 프로퍼티 선언이고, = 뒤는 { 인자1, 인자2 -> 함수 내용 } 으로 구성되어있다.
-> 뒤에 함수 내용(반환 값)을 작성한다.
val sum = { x: Int, y: Int -> x + y }
람다 식 안에서 반환 타입을 추론할 수 있으면, 반환 타입을 명시하지 않아도 된다.
val list = listOf(1, 2, 3, 4)
println( list.map{ n -> "[$n]" } )
결과 : [[1], [2], [3], [4]]
it 으로 만든다.인자 -> 함수 내용 구성을 it을 사용한 함수 내용 으로 간소화할 수 있다.val list = listOf(1, 2, 3, 4)
println( list.map{ "$it" } )
결과 : [1, 2, 3, 4]
val list = listOf('a', 'b', 'c', 'd')
val result = list.map{"${it.uppercaseChar()"}
결과 : [A, B, C, D]
val ints = listOf(-3, -1, 1, 3, 5)
println(ints.filter { it > 0 })
결과 : [1, 3, 5]
val list = listOf(9, 11, 23, 32)
println( list.joinToString(" ") { "$it" } )
결과 : 9 11 23 32joinToString() 의 마지막 인자를 람다 로 지정해 list의 각 원소를 String으로 반환하고, 변환한 String 사이에 " " 를 붙여 하나로 합쳐 반환한 식이다.var str = strings
.filter { it.length == 5 }
.sortedBy { it }
.map { it.uppercase() }_ 로 표시한다.val map = mapOf<Int, String>(1 to "one", 2 to "two", 3 to "three")
map.forEach { (_, value) -> println("$value!") }
결과 :
one!
two!
three!val map = mapOf<Int, String>(1 to "one", 2 to "two", 3 to "three")
println(map.mapValues { entry -> "${entry.value}!" })
println(map.mapValues { (key, value) -> "$value!" })
결과 :
{1=one!, 2=two!, 3=three!}
{1=one!, 2=two!, 3=three!}
{ a -> ... } // 인자 한 개
{ a, b -> ... } // 인자 두 개
{ (a, b) -> ... } // 분리된 Pair
{ (a, b), c -> ... } // 분리된 Pair 와 다른 인자반환 타입 을 자동으로 추론할 수 있지만, 굳이 명시해야 하는 경우에 익명 함수 를 쓸 수 있다.
fun(x: Int, y: Int): Int = x + y
정식 함수 선언처럼 보이지만, 함수 이름이 생략되었다. 함수 블록 안에 함수 내용을 선언할 수 있다.
fun(x: Int, y: Int): Int {
return x + y
}
함수 파라미터의 반환 타입 또한 함수 내용에서 추론 가능하면 생략할 수 있다.
ints.filter(fun(item) = item > 0)
람다와 익명 함수의 return 목적지 차이
return은 따로 달아놓은 label이 없는 경우 가장 주변의fun키워드가 있는 요소로 이동한다.
람다는 사용할 때fun키워드를 따로 쓰지 않기 때문에 람다 밖에 있는fun을 찾아return하게 되고, 익명 함수는fun키워드를 사용하기 때문에 익명함수 자체에서 끝난다.
var sum = 0
ints.filter { it > 0 }.forEach { // 람다 내에서
sum += it // 자유변수 sum을 포착해 사용
}
print(sum)val sum: Int.(Int) -> Int = { other -> plus(other) }
println(5.sum(6)) // 5 + 6
결과 : 11
plus가 수신 객체(프린트문에서 5)에서 호출되는 함수 리터럴이다.
val sum = fun Int.(other: Int): Int = this + other
println(5.sum(6)) // 5 + 6
결과 : 11
위의 함수와 같은 결과를 내놓는다.
익명 함수를 위와 같이 사용하면 함수 리터럴의 수신 타입을 명확하게 할 수 있다.
함수를 선언하면서 수신 객체의 타입을 지정하고, 나중에 사용하려할 때 유용하게 쓸 수 있다.
val va: (String, Int) -> String = { str, n ->
str.repeat(n) + str.repeat(n)
}
val vb: String.(Int) -> String = {
this.repeat(it) + repeat(it)
}
va("lambda", 2) 결과값 : lambdalambda
"lambda".vb(2) 결과값 : lambdalambda
va와 vb는 똑같은 결과를 내놓는다.
vb는 String 파라미터를 괄호 밖으로 옮겨서 String.(Int)로 확장 함수 구문을 사용한다.
여기서 확장 대상 객체(여기서는 String)가 수신 객체가 되고, this를 통해 수신 객체에 접근할 수 있다.
vb의 첫 번째 호출은 this.repeat(it)으로 this를 사용해 명시적인 형태를 사용한다.
두 번째 호출은 this를 생략한 repeat(it) 형태로 되어 있다.
인자가 Int 하나 뿐이기 때문에 it 으로 가리킬 수 있다.