我有一个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会更加惯用。
答案 0 :(得分:12)
您可以使用non-local return从sequence
功能返回:
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()