Dưới đây là một vài biến thể, tùy thuộc vào phong cách bạn muốn sử dụng, nếu bạn có mọi thứ giống nhau hoặc khác loại và nếu danh sách không xác định số lượng mục ...
Các loại hỗn hợp, tất cả không được rỗng để tính giá trị mới
Đối với các kiểu hỗn hợp, bạn có thể xây dựng một loạt các hàm cho mỗi số tham số trông có vẻ ngớ ngẩn, nhưng hoạt động tốt cho các kiểu hỗn hợp:
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
Ví dụ sử dụng:
val risk = safeLet(person.name, person.age) { name, age ->
// do something
}
Thực thi khối mã khi danh sách không có mục rỗng
Hai cách ở đây, đầu tiên để thực thi khối mã khi danh sách có tất cả các mục không phải là null và thứ hai để thực hiện tương tự khi danh sách có ít nhất một mục không phải là rỗng. Cả hai trường hợp đều chuyển một danh sách các mục không rỗng vào khối mã:
Chức năng:
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())
}
}
Ví dụ sử dụng:
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"
Một chút thay đổi để chức năng nhận danh sách các mục và thực hiện các thao tác tương tự:
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())
}
}
Ví dụ sử dụng:
whenAllNotNull("something", "else", "matters") {
println(it.joinToString(" "))
} // output "something else matters"
Các biến thể này có thể được thay đổi để có các giá trị trả về như let()
.
Sử dụng mục không rỗng đầu tiên (Coalesce)
Tương tự như một hàm SQL Coalesce, trả về mục không rỗng đầu tiên. Hai hương vị của hàm:
fun <T: Any> coalesce(vararg options: T?): T? = options.firstOrNull { it != null }
fun <T: Any> Collection<T?>.coalesce(): T? = this.firstOrNull { it != null }
Ví dụ sử dụng:
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"
Các biến thể khác
... Có những biến thể khác, nhưng với nhiều đặc điểm kỹ thuật hơn, điều này có thể được thu hẹp lại.