Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List containing nullable values to a nullable List in Kotlin

Tags:

kotlin

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.

like image 454
Philipp Middendorf Avatar asked Mar 11 '16 17:03

Philipp Middendorf


People also ask

How do you handle nullable in Kotlin?

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.

How do I assign a value to null in Kotlin?

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.

What is @nonnull in Kotlin?

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.


1 Answers

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>
}
like image 128
Alexander Udalov Avatar answered Sep 28 '22 09:09

Alexander Udalov