람다는 값처럼 여기 저기 전달할 수 있는 동작의 모음이다.
{x:Int, y:Int -> x+y}
//파라미터 -> 본문
fun main() {
val items = listOf(Item("item1", 10000), Item("item2", 20000))
println(items.maxByOrNull { it.price }) // 스트림 원소를 it으로 바로 참조 가능하다.
println(items.maxByOrNull(Item::price)) // 메서드 참조도 가능
// 람다를 변수에 직접 할당할 수 있다.
val sum = { x: Int, y: Int -> x + y }
// { println("Hello World") }()
// 람다를 위와 같이 호출할 수도 있지만 더 간단하게 run 함수를 활용하면 람다 본문을 호출할 수 있다.
run { println("Hello World") }
}
람다식을 변수에 저장할 수 있다.
run은 인자로 받은 람다를 실행해주는 라이브러리 함수이다.
코틀린에는 함수 호출 시 맨 뒤에 있는 인자가 람다식이라면, 그 람다를 괄호 밖으로 빼낼 수 있다는 문법 관습이 있다. (코드 형태의 변화)
people.maxBy({p:Person -> p.age})
people.maxBy(){p:Person -> p.age} // 람다가 유일한 인자이므로 마지막 인자로 취급, 괄호 뒤에 람다를 둘 수 있다.
people.maxBy{p:Person -> p.age} //람다가 유일한 인자이고, 괄호 뒤에 람다를 썻다면 호출시 빈 괄호를 없애도 된다.
// 람다의 파라미터가 하나뿐이고, 그 타입을 컴파일러가 추론할 수 있는 경우 it을 바로 쓸 수 있다.
// 람다 파라미터 이름을 따로 지정하지 않은 경우에만 it이라는 이름이 자동으로 만들어진다.
people.maxBy{it.age}
이를 이용하여 개선한 코드
val people = listOf(Person("이몽룡",29), Person("성춘향",31))
//각 사람의 이름만 출력하기 위해 람다를 사용
val names = people.joinToString(separator = " ", transform = {p:Person -> p.name})
//위의 함수 호출에서 함수를 괄호 밖으로 뺀 모습 -> but 간결하지만, 람다의 용도를 직관적으로 알아볼 수는 없다.
val names = people.joinToString(" "){ p : Person -> p.name}
컴파일러가 람다 파라미터의 타입을 추론하지 못하는 경우가 아니면 타입을 생력한다.
컴파일러가 언제 람다 파라미터의 타입을 추론하지 못하는가?
자바와 다르게 코틀린은 람다에서 final이 아닌 변수에 접근이 가능하다.
코틀린에서는 자바와 달리 람다 밖 함수에 있는 final이 아닌 변수에 접근/변경이 가능하다.
→ 람다를 이벤트 핸들러나 다른 비동기적으로 실행되는 코드로 활용하는 경우 함수 호출이 끝난 다음에 로컬 변수가 변경될 수도 있다.