231220 TIL #273 Kotlin #8 람다 - 2

김춘복·2023년 12월 20일
0

TIL : Today I Learned

목록 보기
273/543
post-custom-banner

Today I Learned

람다 이어서 공부!


lazy 지연 컬렉션 계산 asSequence() (자바의 스트림 개념과 비슷)

    people.map(Person::name).filter { it.startsWith("A") }
    
    people.asSequence()
        .map(Person::name) // 시퀀스 상태(중간 연산)
        .filter { it.startsWith("A") } // 시퀀스 상태(중간 연산)
        .toList() // 다시 컬렉션으로(최종 연산)
  • 위의 연산처럼 단순히 map과 filter를 이어서 연산하면 map이 연산결과 리스트를 하나 만들고, 거기서 filter가 실행되어 리스트를 2번 만드는 셈이 된다. 전체 컬렉션에 연산을 적용하는 셈이다.

  • 아래 연산은 people을 시퀀스로 변환한 뒤 map과 filter를 거쳐 마지막으로 리스트를 한번만 반환한다. 이를 지연 시퀀스 연산이라 하는데, 원소들이 중간 처리결과 없이 필요할 때 연쇄적으로 한번에 계산된다. 위와 달리 원소를 한번에 하나씩 처리한다.

  • 아래의 지연 시퀀스 연산은 중간 결과를 생성하지 않기 때문에 메모리 사용량이 적고, 데이터 셋이 많을 경우 성능상 이점이 발생한다.(적으면 오히려 느릴 수도)

  • 따라서 데이터 셋이 많으면 지연 시퀀스 연산이 유리하다.

  • 중간연산은 항상 지연 계산된다. 최종 연산을 호출할 때 비로소 모든 계산이 수행된다.

  • filter를 먼저 수행해 부적절한 원소를 제외하면 연산이 더 빠른 경우도 있다.


수신 객체 지정 람다(lambda with receiver)

수신 객체를 명시하지 않고 람다의 본문 안에서 다른 객체의 메서드를 호출할 수 있게 하는 것

1. with 함수

코틀린에서 제공되는 표준 라이브러리 함수 중 하나로, 특정 객체를 사용하여 수행할 작업을 지정하는 데 사용된다. with 함수는 해당 객체의 메서드 호출이나 프로퍼티 접근을 좀 더 간결하게 표현할 수 있도록 도와준다.

  • 기본구조

    수신 객체(receiver)와 람다 함수(block)를 인자로 받는다. block 내에서는 수신 객체의 메서드나 프로퍼티에 직접 접근할 수 있다.
    with문은 특별한 구문이 아니라 파라미터가 2개 있는 함수라고 보면 된다.
    일반적으로 수신객체는 ()로 받고, 람다는 {}로 받는다.
    첫번째 인자로 받은 객체를 두번째 인자로 받은 람다의 수신 객체로 만든다.
    람다 본문에선 this로 그 수신객체에 접근이 가능하다.

fun <T, R> with(receiver: T, block: T.() -> R): R {
    return receiver.block()
}
  • 예시
    이 예제에서 with 함수를 사용하여 person 객체의 프로퍼티에 접근하고 수정한 후, 람다 내에서 생성한 문자열을 반환한다. 이때 with 함수의 반환값은 람다의 마지막 표현식인 문자열이 된다.
data class Person(var name: String, var age: Int)

fun main() {
    val person = Person("Alice", 30)

    val result = with(person) {
        name = "Bob"
        age += 1
        "The person's name is $name and age is $age."
    }

    println(result) // 출력: "The person's name is Bob and age is 31."
    println(person) // 출력: Person(name=Bob, age=31)
}

2. apply 함수

with와 거의 비슷하지만, 항상 자신에게 전달된 객체(수신 객체)를 반환한다는 점이 다르다.

inline fun <T> T.apply(block: T.() -> Unit): T {
    block()
    return this
}
  • apply 함수는 수신 객체(this)를 그대로 반환하면서, 수신 객체에 대해 수행할 작업을 람다 함수(block)로 받는다. 람다 내에서는 수신 객체의 메서드나 프로퍼티에 직접 접근할 수 있다.

  • with 함수는 특정 객체를 수신 객체로 받지만, apply 함수는 함수를 호출하는 객체가 수신 객체가 된다.

  • with vs apply

    // with 사용
    val resultWith = with(person) {
        name = "Bob"
        age += 1
        "Result from with"
    }

    // apply 사용
    val resultApply = person.apply {
        name = "Charlie"
        age += 1
    }
profile
Backend Dev / Data Engineer
post-custom-banner

0개의 댓글