Voici quelques variantes, selon le style que vous voudrez utiliser, si vous avez tout de types identiques ou différents, et si la liste d'un nombre inconnu d'éléments ...
Types mixtes, tous ne doivent pas être nuls pour calculer une nouvelle valeur
Pour les types mixtes, vous pouvez créer une série de fonctions pour chaque nombre de paramètres qui peuvent sembler ridicules, mais qui fonctionnent bien pour les types mixtes:
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
Exemple d'utilisation:
val risk = safeLet(person.name, person.age) { name, age ->
// do something
}
Exécuter un bloc de code lorsque la liste ne contient aucun élément nul
Deux saveurs ici, d'abord pour exécuter un bloc de code lorsqu'une liste contient tous les éléments non nuls, et deuxièmement pour faire de même lorsqu'une liste a au moins un élément non nul. Les deux cas passent une liste d'éléments non nuls au bloc de code:
Les fonctions:
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())
}
}
Exemple d'utilisation:
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"
Un léger changement pour que la fonction reçoive la liste des éléments et effectue les mêmes opérations:
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())
}
}
Exemple d'utilisation:
whenAllNotNull("something", "else", "matters") {
println(it.joinToString(" "))
} // output "something else matters"
Ces variations peuvent être modifiées pour avoir des valeurs de retour telles que let()
.
Utiliser le premier élément non nul (Coalesce)
Similaire à une fonction SQL Coalesce, renvoie le premier élément non nul. Deux saveurs de la fonction:
fun <T: Any> coalesce(vararg options: T?): T? = options.firstOrNull { it != null }
fun <T: Any> Collection<T?>.coalesce(): T? = this.firstOrNull { it != null }
Exemple d'utilisation:
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"
Autres variations
... Il existe d'autres variantes, mais avec plus de spécifications, cela pourrait être réduit.