Как я могу проверить 2 условия, используя let (или применить и т. Д.) - PullRequest
2 голосов
/ 30 октября 2019

Есть ли более идиоматический способ написать следующее?

foo?.let{
        if(!foo.isBlank()) {
            bar?.let { 
                if(!bar.isBlank()) {
                    println("foo and bar both valid strings")
                }
            }
        }
    }

В сущности, идея состоит в том, что обе строки должны быть ненулевыми и не пустыми, и мне было интересно, есть ли более котлинский способ, чем if(foo.isNullOrEmpty && !bar.isNullOrEmpty)

Ответы [ 6 ]

3 голосов
/ 30 октября 2019

Использовать

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
2 голосов
/ 31 октября 2019

Вы можете использовать sequenceOf и none:

if (sequenceOf(foo, bar).none { it.isNullOrBlank() }) {
    println("foo and bar both valid strings")
}
1 голос
/ 31 октября 2019

Улучшая ответ @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) }
}
1 голос
/ 30 октября 2019

Объявите где-нибудь функцию расширения, используя лямбда-выражения, например:

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")
}
0 голосов
/ 12 ноября 2019

Вы также можете использовать это для произвольного числа аргументов:

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будет иметь обнуляемые типы, даже если они не могут быть нулевыми.

(может быть разумный способ решить это ...)

0 голосов
/ 11 ноября 2019

Это то, что я использую:

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) }

Добавьте больше функций nLet с большим количеством P, если требуется больше аргументов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...