Berikut adalah beberapa variasi, tergantung pada gaya apa yang ingin Anda gunakan, jika Anda memiliki semua jenis yang sama atau berbeda, dan jika daftar jumlah item tidak diketahui ...
Jenis campuran, semua tidak boleh null untuk menghitung nilai baru
Untuk tipe campuran, Anda dapat membuat serangkaian fungsi untuk setiap jumlah parameter yang mungkin terlihat konyol, tetapi berfungsi dengan baik untuk tipe campuran:
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
Contoh penggunaan:
val risk = safeLet(person.name, person.age) { name, age ->
// do something
}
Jalankan blok kode ketika daftar tidak memiliki item nol
Dua ragam di sini, pertama untuk mengeksekusi blok kode ketika daftar memiliki semua item bukan nol, dan kedua untuk melakukan hal yang sama ketika daftar memiliki setidaknya satu item bukan nol. Kedua kasus meneruskan daftar item bukan null ke blok kode:
Fungsi:
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())
}
}
Contoh penggunaan:
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"
Sedikit perubahan agar fungsi menerima daftar item dan melakukan operasi yang sama:
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())
}
}
Contoh penggunaan:
whenAllNotNull("something", "else", "matters") {
println(it.joinToString(" "))
} // output "something else matters"
Variasi ini dapat diubah agar memiliki nilai pengembalian seperti let()
.
Gunakan item non-null pertama (Coalesce)
Mirip dengan fungsi SQL Coalesce, kembalikan item bukan null pertama. Dua jenis fungsi:
fun <T: Any> coalesce(vararg options: T?): T? = options.firstOrNull { it != null }
fun <T: Any> Collection<T?>.coalesce(): T? = this.firstOrNull { it != null }
Contoh penggunaan:
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"
Variasi lainnya
... Ada variasi lain, tetapi dengan lebih banyak spesifikasi, ini dapat dipersempit.