Multiple variable let in Kotlin

后端 未结 12 1168
失恋的感觉
失恋的感觉 2020-11-30 18:48

Is there any way to chain multiple lets for multiple nullable variables in kotlin?

fun example(first: String?, second: String?) {
    first?.let {
        se         


        
12条回答
  •  误落风尘
    2020-11-30 19:39

    Here are a few variations, depending on what style you will want to use, if you have everything of same or different types, and if the list unknown number of items...

    Mixed types, all must not be null to calculate a new value

    For mixed types you could build a series of functions for each parameter count that may look silly, but work nicely for mixed types:

    inline fun  safeLet(p1: T1?, p2: T2?, block: (T1, T2)->R?): R? {
        return if (p1 != null && p2 != null) block(p1, p2) else null
    }
    inline fun  safeLet(p1: T1?, p2: T2?, p3: T3?, block: (T1, T2, T3)->R?): R? {
        return if (p1 != null && p2 != null && p3 != null) block(p1, p2, p3) else null
    }
    inline fun  safeLet(p1: T1?, p2: T2?, p3: T3?, p4: T4?, block: (T1, T2, T3, T4)->R?): R? {
        return if (p1 != null && p2 != null && p3 != null && p4 != null) block(p1, p2, p3, p4) else null
    }
    inline fun  safeLet(p1: T1?, p2: T2?, p3: T3?, p4: T4?, p5: T5?, block: (T1, T2, T3, T4, T5)->R?): R? {
        return if (p1 != null && p2 != null && p3 != null && p4 != null && p5 != null) block(p1, p2, p3, p4, p5) else null
    }
    // ...keep going up to the parameter count you care about
    

    Example usage:

    val risk = safeLet(person.name, person.age) { name, age ->
      // do something
    }   
    

    Execute block of code when list has no null items

    Two flavours here, first to execute block of code when a list has all non null items, and second to do the same when a list has at least one not null item. Both cases pass a list of non null items to the block of code:

    Functions:

    fun  Collection.whenAllNotNull(block: (List)->R) {
        if (this.all { it != null }) {
            block(this.filterNotNull()) // or do unsafe cast to non null collectino
        }
    }
    
    fun  Collection.whenAnyNotNull(block: (List)->R) {
        if (this.any { it != null }) {
            block(this.filterNotNull())
        }
    }
    

    Example usage:

    listOf("something", "else", "matters").whenAllNotNull {
        println(it.joinToString(" "))
    } // output "something else matters"
    
    listOf("something", null, "matters").whenAllNotNull {
        println(it.joinToString(" "))
    } // no output
    
    listOf("something", null, "matters").whenAnyNotNull {
        println(it.joinToString(" "))
    } // output "something matters"
    

    A slight change to have the function receive the list of items and do the same operations:

    fun  whenAllNotNull(vararg options: T?, block: (List)->R) {
        if (options.all { it != null }) {
            block(options.filterNotNull()) // or do unsafe cast to non null collection
        }
    }
    
    fun  whenAnyNotNull(vararg options: T?, block: (List)->R) {
        if (options.any { it != null }) {
            block(options.filterNotNull())
        }
    }
    

    Example usage:

    whenAllNotNull("something", "else", "matters") {
        println(it.joinToString(" "))
    } // output "something else matters"
    

    These variations could be changed to have return values like let().

    Use the first non-null item (Coalesce)

    Similar to a SQL Coalesce function, return the first non null item. Two flavours of the function:

    fun  coalesce(vararg options: T?): T? = options.firstOrNull { it != null }
    fun  Collection.coalesce(): T? = this.firstOrNull { it != null }
    

    Example usage:

    coalesce(null, "something", null, "matters")?.let {
        it.length
    } // result is 9, length of "something"
    
    listOf(null, "something", null, "matters").coalesce()?.let {
        it.length
    }  // result is 9, length of "something"
    

    Other variations

    ...There are other variations, but with more of a specification this could be narrowed down.

提交回复
热议问题