Is there any way to chain multiple lets for multiple nullable variables in kotlin?
fun example(first: String?, second: String?) {
first?.let {
se
Here are a few variations, depending on what style you will want to use, if you have everything of same or different types, and if the list unknown number of items...
For mixed types you could build a series of functions for each parameter count that may look silly, but work nicely for mixed types:
inline fun safeLet(p1: T1?, p2: T2?, block: (T1, T2)->R?): R? {
return if (p1 != null && p2 != null) block(p1, p2) else null
}
inline fun 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 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 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
Example usage:
val risk = safeLet(person.name, person.age) { name, age ->
// do something
}
Two flavours here, first to execute block of code when a list has all non null items, and second to do the same when a list has at least one not null item. Both cases pass a list of non null items to the block of code:
Functions:
fun Collection.whenAllNotNull(block: (List)->R) {
if (this.all { it != null }) {
block(this.filterNotNull()) // or do unsafe cast to non null collectino
}
}
fun Collection.whenAnyNotNull(block: (List)->R) {
if (this.any { it != null }) {
block(this.filterNotNull())
}
}
Example usage:
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"
A slight change to have the function receive the list of items and do the same operations:
fun whenAllNotNull(vararg options: T?, block: (List)->R) {
if (options.all { it != null }) {
block(options.filterNotNull()) // or do unsafe cast to non null collection
}
}
fun whenAnyNotNull(vararg options: T?, block: (List)->R) {
if (options.any { it != null }) {
block(options.filterNotNull())
}
}
Example usage:
whenAllNotNull("something", "else", "matters") {
println(it.joinToString(" "))
} // output "something else matters"
These variations could be changed to have return values like let().
Similar to a SQL Coalesce function, return the first non null item. Two flavours of the function:
fun coalesce(vararg options: T?): T? = options.firstOrNull { it != null }
fun Collection.coalesce(): T? = this.firstOrNull { it != null }
Example usage:
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"
...There are other variations, but with more of a specification this could be narrowed down.