【发布时间】:2021-07-18 14:11:24
【问题描述】:
我正在学习来自 Java 的 Kotlin,我偶然发现了一个意想不到的行为。 我注意到,在我下面的代码中,我似乎不小心在错误的位置声明了一个新的 lambda,而不是 使用 我已经拥有的那个。我该如何解决这个问题?
我写了这两个声明:
/**
* Dataclass used as an example.
*/
data class Meeple(var name: String, var color: String = "translucent")
/**
* Function to map from a List<T> to a new List of equal length,
* containing the ordered elements received by applying a Mapper's map
* function to every element of the input List.
*
* @param T Type of input List-elements
* @param O Type of output List-elements
* @param mapper The mapping function applied to every input element.
* @return The List of output elements received by applying the mapper on all
* input elements.
*/
fun <T, O> List<T>.map(mapper: (T) -> O?): List<O?> {
val target = ArrayList<O?>();
for (t in this) {
val mapped: O? = mapper.invoke(t)
target.add(mapped);
}
return target;
}
数据类只是一个简单对象的虚拟示例。 List.map 扩展函数旨在从列表的元素映射到新类型并返回该新类型的新列表,就像 Java 中的 Stream.map 一样。
然后我创建一些虚拟的Meeples 并尝试将它们映射到各自的名称:
fun main(args: Array<String>) {
val meeples = listOf(
Meeple("Jim", "#fff"),
Meeple("Cassidy"),
Meeple("David", "#f00")
)
var toFilter: String = "Cassidy"
val lambda: (Meeple) -> String? =
{ if (it.name == toFilter) null else it.name }
toFilter = "Jim"
for (name in meeples.map { lambda }) {
println(name ?: "[anonymous]") // This outputs "(Meeple) -> kotlin.String?" (x3 because of the loop)
}
}
我这样做是为了检查 lambda 的行为,以及它稍后是否会过滤“Jim”或“Cassidy”,我的预期是后者,因为那是 lambda 初始化时 toFilter 的状态。
但是我得到了完全不同的结果。 invoke 方法虽然被 IntelliJ 描述为 (T) -> O?,但似乎产生了 lambda 的名称而不是 Meeple 的名称。
看来,对 meeples.map { lambda } 的调用并没有像我预期的那样绑定 lambda,而是创建了一个新的 lambda,它返回 lambda 并可能在内部调用 toString。
我将如何实际调用真正的 lambda 方法,而不是声明一个新方法?
【问题讨论】:
-
以防万一,
map函数存在于 Kotlin 标准库中。 -
@AdamMillerchip 我也很怀疑,尽管这更像是一个可以编写一些 lambda 表达式的现场示例。不过感谢您的提示:)
-
我想通了。它需要是一个简单的参数,而不是包裹在
{ }中。它应该看起来像这样:for (name in meeples.map(lambda)) {
标签: kotlin