是否有更惯用的方式写以下内容?
foo?.let{
if(!foo.isBlank()) {
bar?.let {
if(!bar.isBlank()) {
println("foo and bar both valid strings")
}
}
}
}
基本上,这个想法是两个字符串都应该为nonNull和nonEmpty,我想知道是否还有比if(foo.isNullOrEmpty && !bar.isNullOrEmpty)
更好的Kotlin方式
答案 0 :(得分:3)
使用此
fun <T, R, S> biLet(lhs: T, rhs: R, block: (T, R) -> S): S? = if (lhs != null && rhs != null) block(lhs, rhs) else null
用作
biLet(foo, bar) { safeFoo, safeBar ->
}
编辑:字符串的变体
fun <T: CharSequence?, S> biLet(lhs: T, rhs: T, block: (T, T) -> S): S? =
if (lhs.isNotNullOrBlank() && rhs.isNotNullOrBlank()) block(lhs, rhs) else null
答案 1 :(得分:2)
您可以使用sequenceOf
和none
:
if (sequenceOf(foo, bar).none { it.isNullOrBlank() }) {
println("foo and bar both valid strings")
}
答案 2 :(得分:1)
在某处使用lambda声明扩展功能,例如:
inline fun String.ifNotEmpty(bar: String, function: () -> Unit) {
if (this.isNotEmpty() && bar.isNotEmpty()) {
function.invoke()
}
}
并将其用作:
val foo = "foo-value"
val bar = "bar-value"
foo.ifNotEmpty(bar) {
println("foo and bar both valid strings")
}
答案 3 :(得分:1)
改进@Francesc的答案,我创建了nLet版本
fun <S> nLet(vararg ts: Any?, block: (Array<out Any?>) -> S): S? =
if (ts.none { when (it) { is String -> it.isNullOrEmpty() else -> it == null } }) block(ts) else null
您可以像这样使用它
nLet (1, 2 , 3, "a", "B", true) { ts ->
ts.forEach { println(it) }
}
答案 4 :(得分:0)
这是我使用的:
fun <P1, P2, R> nLet(p1: P1?, p2: P2?, block: (P1, P2) -> R?): R? =
p1?.let { p2?.let { block(p1, p2) } }
用法:
nLet(foo, bar) { f, b -> doStuff(f, b) }
如果需要更多参数,请添加更多带有P
的nLet函数。
答案 5 :(得分:0)
您也可以将其用于任意数量的参数:
fun <P, R> nLet(vararg ts: P?, block: (Array<out P?>) -> R): R? =
ts.takeIf { it.none { it == null } }?.let { block(it) }
用法:
nLet(foo, bar, dog) { (f, b, d) -> doStuff(f, b, d) }
这有效,但是f
,b
和d
将具有可为空的类型,即使它们不能为空。
(解决这个问题的方法可能很聪明...)