람다는 다른 함수에 넘길 수 있는 작은 코드 조각을 의미한다. 람다를 통해 공통 코드 구조를 라이브러리 함수로 뽑아낼 수 있는데, 심지어 처음부터 람다를 고려하지 않고 만든 라이브러리도 사용 가능하다. 이제부터 람다로 프로그래밍하는 법을 알아보도록 하자.
코틀린에서는 람다 식을 통해 함수를 선언하는 대신 코드 블록을 직접 함수의 인자로 전달할 수 있다. 다음과 같이 자바는 무명 내부 클래스를 선언하기 때문에 코드가 번잡스러워진다.
/* Java */
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) { //무명 내부 클래스의 선언
/*클릭 시 수행할 동작 */
}
});
/* Kotlin */
button.setOnClickListener{ /*클릭 시 수행할 동작 */}
위에서 볼 수 있는 것처럼, 람다는 주로 메서드가 하나뿐인 무명 객체 대신 많이 사용한다.
람다를 통해 컬렉션을 편리하게 처리할 수 있는 라이브러리를 사용할 수 있다. 예를 들어, 아래에서 볼 수 있는 것처럼 모든 컬렉션에 대해 maxBy
함수를 호출하여 가장 큰 값을 찾을 수 있는데, 이때 maxBy 함수는 비교할 값을 돌려주는 함수, 즉 it.age
를 인자로 받는다.
>>> val people = listOf(Person("Alice", 29), Person("Bob", 31))
>>> println(people.maxBy { it.age }) //나이 프로터피를 비교해 가장 큰 값을 돌려줌
Person(name=Bob, age=31)
people.maxBy(Person::age) //위와 같은 역할을 하는 코드
람다 식은 항상 중괄호 사이에 위치하고, 화살표(->
)가 인자 목록과 람다 본문을 구분해준다. 또한 람다 식을 변수에 저장하기도 하는데, 이렇게 변수에 저장한 람다를 다른 일반 함수와 마찬가지로 다룰 수 있다(즉, 변수 이름 뒤에 괄호를 놓고 그 안에 필요한 인자를 넣어 호출 가능하다).
>>> val sum = { x: Int, y: Int -> x+y}
>>> println(sum(1, 2)) //방법 1
또한 { println(42) }()
처럼 직접 람다를 호출할 수 있지만, 이는 읽기도 어렵고 쓸모도 없다. 만약 이렇게 코드의 일부분을 블록으로 실행할 필요가 있다면 run
을 사용한다(run은 인자로 받은 람다를 실행해 주는 라이브러리 함수). 따라서 run{ println(42) }
처럼 사용 가능하다.
따라서 위에서 언급한 maxBy 함수는 people.maxBy ( { p: Person -> p.age } )
처럼 사용할 수 있다. 또한 코틀린에서는 함수 호출 시 맨 뒤에 있는 인자가 람다 식이라면 그 람다를 괄호 밖으로 빼낼 수 있다. people.maxBy () { p: Person -> p.age }
또한 람다가 어떤 함수의 유일한 인자이고, 괄호 뒤에 람다를 썼다면 호출 시 빈 괄호를 없앨 수 있다. people.maxBy { p: Person -> p.age }
또한, 람다의 파라미터 타입을 생략하면 컴파일러가 자동으로 추론해준다. 따라서 명시할 필요가 없다. people.maxBy { p -> p.age }
마지막으로, 파라미터 이름을 디폴트 이름인 it
으로 만들 수 있다. people.maxBy { it.age }
(현아가 많이 쓴다고 했음💙)
<aside> 📌 여러 줄로 이루어진 람다의 경우, 본문의 맨 마지막에 있는 식이 람다의 결과 값이 된다.
</aside>
forEach
함수는 각각의 원소에 대해 수행할 작업을 람다로 받는다.
fun printMessagesWithPrefix(messages: Collection<String>, prefix: String) {
messages.forEach {
println("$prefix $it")
}
}
>>> val errors = listOf("403 Forbidden", "404 Not Found")
>>> printMessagesWithPrefix(errors, "Error:")
Error: 403 Forbidden
Error: 404 Not Found
코틀린의 람다 안에서는 파이널 변수가 아닌 변수에 접근이 가능하다. 또한 람다 안에서 바깥의 변수를 변경해도 된다.