Ось кілька варіантів, залежно від того, який стиль ви хочете використовувати, якщо у вас є все однакові або різні типи, і якщо в списку невідома кількість елементів ...
Змішані типи не повинні мати значення для обчислення нового значення
Для змішаних типів ви можете створити ряд функцій для кожного підрахунку параметрів, які можуть виглядати нерозумно, але добре працювати для змішаних типів:
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 collectino
}
}
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()
.
Використовуйте перший ненульовий елемент (Coalesce)
Подібно до функції 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"
Інші варіації
... Існують і інші варіанти, але, якщо більше специфікації, це може бути звужене.