
만약 고차함수와 람다를 먼저 보고 오지 않으셨다면 필자가 정리한 글이나 다른 분들의 글을 보고 오시는걸 추천 드립니다.
[안드로이드] 고차함수와 람다란?

위 그림처럼 스코프 함수에는 'let', 'run', 'with', 'apply', 'also'로 총 5개가 있습니다. 이것들을 활용하면 코드를 훨씬 간결하게 만들어 줄 수 있습니다.
이 5개의 종류에도 서로 차이가 있는데, 그중 가장 큰 차이는 람다식의 접근 방법과 반환 방법입니다. 그럼 이제 확장 함수들에 대해 하나씩 알아보도록 하겠습니다.
fun<T> T.apply(block: T.() -> Unit): T
apply 람다함수의 리턴값은 없고, context object인 T를 리턴하게 되어있다. 즉, 람다함수 블럭내에서는 리턴값을 신경쓰지 않으며, 람다에서 생성된 객체를 반환해준다.
inline fun <T> T.also(block: (T) -> Unit): T
수신 객체인 람다가 전달된 수신 객체를 전혀 사용하지 않거나 수신 객체의 타입을 변경하지 않고 사용할 경우 also를 씁니다. also는 apply와 마찬가지로 람다에서 생성된 객체를 반환하므로 블록 함수가 다른 값을 반환하는 경우 also를 사용할 수 없습니다.
inline fun <T, R> T.let(block: (T) -> R): R
let의 인자는 람다함수 하나로, 람다함수에 해당하는 스코프 블럭을 바로 사용할 수 있다. 보통 저장된 값이 null 이 아닌 경우에 코드를 실행해야 하거나, Nullable한 객체를 다른 Nullable 객체로 반환하는 경우, 또 단일 지역 변수의 범위를 제한 하는 경우에 사용합니다.
inline fun <T, R> with (receiver: T, block: T.() -> R): R
Non-nullable 수신 객체이고 결과가 따로 필요하지 않을 경우에 사용합니다.
inline fun <R> run(block: () -> R): R
inline fun <T, R> T.run(block: T.() -> R): R
run에는 두가지 정의가 있습니다. 수신 객체가 없이 단일 람다 R로 되어있는 것과, 수신 객체 T로 정의된 두가지 경우가 있습니다. 둘다 리턴값은 람다의 리턴값을 사용합니다. run은 어떤 값을 계산할 필요가 있거나 여러개의 지역 변수의 범위를 제한하려 할때 사용합니다.
필자는 위 함수들중에 개발하면서 apply를 가장 많이 써봤는데, 다른 함수들도 써보면서 경험할 필요가 있어보입니다. 나중에 쓰기도 하고 알고 있으면 코드가독성을 높이는데 좋을테니까요.