列表包含可以在Kotlin中为可空列表的可空值

时间:2016-03-11 17:23:07

标签: kotlin

我有一个List<T?>包含空值(我想,这是不被禁止的)。如果此列表的一个元素为null,我希望整个列表为null(Haskell人称之为sequence)。以下伪代码演示了我想要做的事情:

fun <T> sequence(a : List<T?>) : List<T>? {
    return 
        a.fold(
            listOf(),
            { 
                prevArray, element -> 
                    if(element == null) null else prevArray + element 
            })
}

这是伪代码,因为编译器抱怨Null can not be a value of a non-null type kotlin.collections.List<T>

在Kotlin表达我想要的东西的惯用方法是什么?使用Java的Optional类型,这至少是可编译的:

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) 
            })
}

但是Kotlin在null处理方面有许多运算符和功能,所以我认为直接使用null会更加惯用。

2 个答案:

答案 0 :(得分:12)

您可以使用non-local returnsequence功能返回:

fun <T> sequence(a: List<T?>): List<T>? {
    return a.fold(listOf()) {
        prevArray, element ->
        if (element == null) return null else prevArray + element
    }
}

但是,我会用简单的if - 表达式来解决你所描述的问题,以防止发生大量列表分配,因为列表添加会为每个元素创建一个由数组支持的新列表。未经检查的强制转换警告在下面被禁止,因为编译器无法确定该列表在该点没有包含空值,尽管我们可以清楚地看到这种情况:

fun <T> sequence(a: List<T?>): List<T>? {
    @Suppress("UNCHECKED_CAST")
    return if (a.any { it == null }) null else a as List<T>
}

答案 1 :(得分:0)

使用Konad库,您现在可以执行以下操作:

fun <T> sequence(a : List<T?>) : List<T>? = a.flatten()?.toList()