본문 바로가기

Android

[Kotlin] let 사용방법 및 주의

1.  filter 의 결과물을 let 으로 1개 또는 여러개의 작업수행

 

val numbers = mutableListOf("one", "two", "three", "four", "five")
numbers.map { it.length }.filter { it > 3 }.let { 
    println(it)
    // and more function calls if needed
} 

위의 예시에서 만약 let{ } 블럭 안에 하나의 function 만을 포함하며 매개변수가 1개의 it일 경우 

.let(::println)

으로 대체가능하다. 

 

 

 

2. Not Null  체크

 

val str: String? = "Hello"   
//processNonNullString(str)       // compilation error: str can be null
val length = str?.let { 
    println("let() called on $it")        
    processNonNullString(it)      // OK: 'it' is not null inside '?.let { }'
    it.length
}

위의 예시처럼 ?.let 을 통해 해당 변수 또는 결과물의 null 이 아닌지 여부를 체크한다. null이 아닐 경우에 {} 블록이 동작한다. 

 

 

 

3. 결과 값 대입

 

val numbers = listOf("one", "two", "three", "four")
val modifiedFirstItem = numbers.first().let { firstItem ->
    println("The first item of the list is '$firstItem'")
    if (firstItem.length >= 5) firstItem else "!" + firstItem + "!"
}.toUpperCase()
println("First item after modifications: '$modifiedFirstItem'")

first() 의 결과물로 .let 을 진행하면서 블록 {} 내에 firstItem 이 결과물이다.

modifiedFirstItem 에 지정되어질 값으로 firstItem 값이 5 이상일 경우 firstItem 값이 그렇지 않으면 앞뒤로 "!" 가 붙으며 모두 대문자로 변경된 값이 지정된다.

 

 

이처럼 let 은 단순히 null 체크 뿐 아니라 하나의 변수 또는 결과값을 하나 또는 여러개의 함수에서 쓰게되어 {} 블록으로 묶어 줌으로써 좀 더 간결하게 코드를 작성할 수 있다. 

 

 

 

4. if NotNull else Null

 

 val tempMap = mutableMapOf<String, String>()
    private fun calculatedFee(): Int? {
        //...
        return 1000
    }

    fun A() {
        calculatedFee()?.let {
            //null 이 아닐경우
            println("The fee is not null")
            tempMap.put("hi","hi")
            //(중요) 위의 tempMap 리턴이 null 이 아니면 하단의 ?: run {} 블록이 동작해버리게 된다.
            //println("ok!")
            //위의 println 주석을 풀면 아래의 null 일 경우의 블록은 정상동작한다.
        } ?: run {
            println("The fee is null")
            //null 일 경우
        }
    }

기본적으로 ?.let{...} :? run{} 는 값이 null 일 경우까지 처리해주는 코드이다.  

 

*** 주의

위의 코드에서 ?.let{} 안의 블록에서 행해지는 코드의 내부 결과가 Map.put()  객체를 리턴하는 케이스의 경우, ?: run{} 의 스코프까지 동작되어 ?.let{} 블럭과 ?:run{} 블럭 모두 작동되어 버린다. Map.put() 리턴 객체의 경우에만 이런 케이스가 발생하는 것 같다. List.add() 는 정상적으로 NotNull 이 동작한다. 다른 케이스도 좀 더 테스트 해봐야겠다.

 

위의 코드를 돌리면

으로 결과가 나타난다.

println("ok!") 만 주석해제하면 정상동작 한다. 

 

(이것 때문에 한참 삽질...) 

 

혹시 정확한 이유를 아신다면 댓글좀 남겨주세요 ㅜ 

 

 

 

(출처)

kotlinlang.org/docs/scope-functions.html#let

 

Scope functions | Kotlin

 

kotlinlang.org