I have a List<T?>
containing null values (which, I suppose, is not forbidden). If one element of this list is null, I want the entire list to be null (what Haskell people call sequence
). The following pseudocode demonstrates what I want to do:
fun <T> sequence(a : List<T?>) : List<T>? {
return
a.fold(
listOf(),
{
prevArray, element ->
if(element == null) null else prevArray + element
})
}
This is pseudocode because the compiler complains that Null can not be a value of a non-null type kotlin.collections.List<T>
.
What's the idiomatic way to express what I want to in Kotlin? Using Java's Optional
type, this is at least compilable:
fun <T> sequence(a : List<T?>) : Optional<List<T>> {
return
a.fold(
Optional.of(listOf()),
{
prevArray, element ->
if(element == null) Optional.empty<List<T>>() else Optional.of(prevArray + element)
})
}
But Kotlin has many operators and functionalities regarding null handling, so I thought using null directly would be more idiomatic.
type can hold either a string or null , whereas a String type can only hold a string. To declare a nullable variable, you need to explicitly add the nullable type. Without the nullable type, the Kotlin compiler infers that it's a non-nullable type.
In an effort to rid the world of NullPointerException , variable types in Kotlin don't allow the assignment of null . If you need a variable that can be null, declare it nullable by adding ? at the end of its type. Declares a non- null String variable.
Nullable and Non-Nullable Types in Kotlin – Kotlin type system has distinguish two types of references that can hold null (nullable references) and those that can not (non-null references). A variable of type String can not hold null. If we try to assign null to the variable, it gives compiler error.
You can use a non-local return to return from the sequence
function:
fun <T> sequence(a: List<T?>): List<T>? {
return a.fold(listOf()) {
prevArray, element ->
if (element == null) return null else prevArray + element
}
}
However, I would solve the problem you described with a simple if
-expression, to prevent lots of list allocations which happen because the list addition creates a new list backed by array for each element. The unchecked cast warning is suppressed below because the compiler cannot figure out that the list does not contain nulls at that point, although we can clearly see that is the case:
fun <T> sequence(a: List<T?>): List<T>? {
@Suppress("UNCHECKED_CAST")
return if (a.any { it == null }) null else a as List<T>
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With