kotlin - Kotlin 中的多变量 let

有没有办法在 kotlin 中为多个可为空的变量链接多个 let?

fun example(first: String?, second: String?) {
    first?.let {
        second?.let {
            // Do something just if both are != null
        }
    }
}

我的意思是,像这样:

fun example(first: String?, second: String?) {
    first?.let && second?.let { 
        // Do something just if both are != null
    }
}

最佳答案

这里有一些变化,具体取决于您要使用的样式、您是否拥有相同或不同类型的所有内容以及列表中的项目数量是否未知...

混合类型,都不能为空才能计算新值

对于混合类型,您可以为每个参数计数构建一系列函数,这些函数可能看起来很傻,但对于混合类型来说效果很好:

inline fun <T1: Any, T2: Any, R: Any> safeLet(p1: T1?, p2: T2?, block: (T1, T2)->R?): R? {
    return if (p1 != null && p2 != null) block(p1, p2) else null
}
inline fun <T1: Any, T2: Any, T3: Any, R: Any> 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 <T1: Any, T2: Any, T3: Any, T4: Any, R: Any> 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 <T1: Any, T2: Any, T3: Any, T4: Any, T5: Any, R: Any> 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

示例用法:

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

当列表没有空项时执行代码块

这里有两种风格,第一种是在列表包含所有非空项时执行代码块,第二种是在列表至少有一个非空项时执行相同的代码块。两种情况都将非空项列表传递给代码块:

功能:

fun <T: Any, R: Any> Collection<T?>.whenAllNotNull(block: (List<T>)->R) {
    if (this.all { it != null }) {
        block(this.filterNotNull()) // or do unsafe cast to non null collection
    }
}

fun <T: Any, R: Any> Collection<T?>.whenAnyNotNull(block: (List<T>)->R) {
    if (this.any { it != null }) {
        block(this.filterNotNull())
    }
}

示例用法:

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"

让函数接收项目列表并执行相同操作的细微变化:

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

fun <T: Any, R: Any> whenAnyNotNull(vararg options: T?, block: (List<T>)->R) {
    if (options.any { it != null }) {
        block(options.filterNotNull())
    }
}

示例用法:

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

可以将这些变体更改为具有返回值,例如 let()

使用第一个非空项(合并)

类似于 SQL Coalesce 函数,返回第一个非空项。两种风格的函数:

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

示例用法:

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"

其他变体

...还有其他变体,但如果有更多规范,这可能会缩小范围。

https://stackoverflow.com/questions/35513636/

相关文章:

kotlin - Kotlin 中有构造函数引用吗?

kotlin - Kotlin中折叠和减少之间的区别,何时使用?

syntax - Kotlin 二级构造函数

generics - 如何在 Kotlin 中将 TypeToken + 泛型与 Gson 一起使用

android - Kotlin Android 启动新 Activity

function - 何时在 Kotlin 中使用内联函数?

kotlin - "experimental"Kotlin协程可以在生产中使用吗?

loops - Kotlin 中 `break` 中的 `continue` 和 `forEach`

enums - Kotlin 中具有反向查找的有效枚举?

kotlin - 在 Kotlin 中创建抽象类的实例