接收转换映射函数发送到 `List<>.mapNotNull()`

Receive transformation map function to send into `List<>.mapNotNull()`

我正在尝试编写一个类似 transform 的函数,它接收一个将在 mapNotNull 内部使用的函数,但我找不到实现它的方法。

例子

val items: List<String?> = listOf(null, "cosa")

fun transform(transformer: (String) -> String?) {
    items.mapNotNull(transformer) // <-------------------------------------- THIS DOES NOT COMPILE
}

fun main() {
    val items: List<String?> = listOf(null, "cosa")

    val transformer: (String) -> String? = {
        null    
    }

    val map = transform(transformer)

    print(map)

}

您可以在此处查看其工作原理:play.kotlinlang

如何声明 fun transform 的参数才能在 mapNotNull 中传递它?

您有一个可为空字符串的列表。

mapNotNull 将变换函数应用于列表中的每个元素,然后检查此函数的结果是否为空。所以在这种情况下,它在 transformer 函数中传递了一个可为空的字符串,而该函数肯定不能是 (String) -> String? 类型,因为这里的参数是一个不可为空的字符串。

您应该将转换器函数声明为 (String?) -> String?,或者在调用 mapNotNull:

之前从列表中删除空值
items.filterNotNull().mapNotNull(transformer)

另一种选择是将 transformer 包装到 lambda 函数中,然后再将其传递给 mapNotNull 并在那里处理空元素,例如:

items.mapNotNull { e -> e?.let(transformer) }

这仅在元素不为空时才将 transformer 函数应用于元素。

mapNotNull函数定义为:

public inline fun <T, R : Any> Iterable<T>.mapNotNull(transform: (T) -> R?): List<R>

换句话说,transform lambda 的参数类型是 T,其中 T 是正在操作的 Iterable 的类型。在你的例子中,你的迭代是 List 类型 String?.

因此,您需要将转换器声明为 (String?) -> String? 类型,并且只有该转换的非空结果才会包含在结果中。

为了更新您在 play.kotlinlang 上提供的代码,进行一些额外的修改以使类型声明更加地道——请注意,尽管有些奇怪,但我大部分都保留了代码原样使用附加 transform 函数:

val items = listOf<String?>(null, "cosa")

fun transform (transformer: (String?) -> String?): List<String> {
    return items.mapNotNull(transformer)
}

fun main() {
    val items = listOf<String?>(null, "cosa")

    val transformer: (String?) -> String? = {
        // this of course means the output of transform will always be empty
        null    
    }

    val map = transform(transformer)

    print(map)
}