[Kotlin in Action] 21. 람다식

반응형
728x90
반응형

람다식

코드 블록을 함수 인자로 넘기기

함수형 프로그래밍에서는 클래스를 선언하고 그 클래스의 인스턴스를 함수에 넘기는 대신, 함수를 직접 다른 함수에 전달할 수 있다. 람다 식을 사용하면 코드가 더욱 더 간결해진다.
람다 식을 사용하면 함수를 선언할 필요가 없고 코드 블록을 직접 함수의 인자로 전달할 수 있다.

https://jjunsu.tistory.com/34

함수에 인자로 넘기면서 바로 람다를 정의하는 경우가 대부분이다. 코틀린의 람다식은 항상 중괄호로 둘러싸여있다. 인자 목록 주변에 괄호가 없다는 사실을 꼭 기억하라. 화살표(->)가 인자 목록과 람다 본문을 구분해준다.

 

1) 람다식을 변수에 저장해보자.

fun main() {
    // 람다식을 변수에도 저장할 수 있다.
    val sum = { x: Int, y: Int -> x + y }
    println(sum(1, 2)) // 변수에 저장된 람다를 호출
}

 

2) 람다식을 직접 호출해보자.

fun main() {
    // 람다식을 직접 호출해도 된다.
    run {println(42)} // run : 인자로 받은 람다를 실행해주는 라이브러리 함수
}

 

 

예제 : 버튼 클릭에 따른 동작 정의하기

클릭 이벤트를 처리하는 리스너를 추가한다. 이 리스너는 onClick 이라는 메서드가 들어있는 onClickListener를 구현해야한다.

 

1) Java의 익명 내부 클래스로 구현하기

button.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View view) {
        클릭 시 수행할 동작
    }
});

 

2) Kotlin 람다로 구현하기

button.setOnClickListener {  클릭 시 수행할 동작  }

 

 

람다식의 코드 중복 제거

코드에서 중복을 제거하는 것은 프로그래밍 스타일을 개선하는 중요한 방법이다.

 

예제

사람의 이름과 나이를 저장하는 Person 클래스를 사용하자.

data class Person(val name: String, val age: Int)

 

사람들로 이뤄진 리스트가 있고, 그중에 가장 연장자를 찾고싶다.
람다를 사용해본 경험이 없는 개발자라면 루프를 써서 직접 검색을 구현할 것이다.

 

  • 컬렉션을 직접 검색
// 컬렉션을 직접 검색하기
fun findTheOldest(people: List<Person>) {
    var maxAge = 0 // 가장 많은 나이를 저장한다.
    var theOldest: Person? = null // 가장 연장자인 사람을 저장한다.

    for (person in people) {
        if (person.age > maxAge) { // 현재까지 발견한 최연장자보다 더 나이가 많은 사람 찾으면 최댓값 바꾼다.
            maxAge = person.age
            theOldest = person
        }
    }

    println(theOldest)
}

 

  • 호출
fun main(args: Array<String>) {
    val people = listOf(Person("Alice", 29), Person("Bob", 31))
    findTheOldest(people) // Person(name=Bob, age=31)

 

 

람다식 사용해보기

1) 나이 프로퍼티를 비교해서 값이 가장 큰 원소 찾기

println(people.maxByOrNull { it.age }) // Person(name=Bob, age=31)

 

2) 멤버 참조를 사용하여 컬렉션 검색하기

println(people.maxByOrNull(Person::age)) // Person(name=Bob, age=31)

 

3) 파라미터 타입 명시

println(people.maxByOrNull ({ p: Person -> p.age }))

 

4) 이름 붙인 인자를 사용하여 람다 넘기기

val personList = listOf(Person("이몽룡", 29), Person("성춘향", 31))
val names = personList.joinToString(separator = " ", transform = { p: Person -> p.name})
println(names) // 이몽룡 성춘향

 

5) 람다를 괄호 밖에 전달하기

함수 호출 시, 맨 뒤에 있는 인자가 람다식이라면 그 람다를 괄호 밖으로 빼낼 수 있다.

val names2 = personList.joinToString(" ") { p: Person -> p.name}
println(names2) // 이몽룡 성춘향

 

6) 파라미터 타입을 생략(컴파일러가 추론)

println(people.maxByOrNull { p -> p.age })

 

7) 람다의 파라미터가 하나뿐이고, 그 타입을 컴파일러가 추론할 수 있는 경우 it 사용 가능

  • it : 자동 생성된 파라미터 이름 (람다 이름을 지정하지 않았을 경우에만 디폴트 파라미터 이름 it 사용)
println(people.maxByOrNull { it.age }) // 나이 프로퍼티를 비교해서 값이 가장 큰 원소 찾기

 

8) 람다를 변수에 저장할 때는 파라미터의 타입을 추론할 문맥이 존재하지 않아서, 파라미터 타입 명시해야한다.

val getAge = { p: Person -> p.age }
println(people.maxByOrNull(getAge))

 

9) 본문이 여러 줄로 이뤄진 경우 본문의 맨 마지막에 있는 식이 람다의 결과값이 된다.

val sum = { x: Int, y: Int ->
    println("Computing the sum of $x and $y...")
    x + y
}
println(sum(1, 2)) // 3

 

 

 

반응형

Designed by JB FACTORY