为什么Kotlin需要函数引用语法?

时间:2017-04-13 15:39:40

标签: kotlin

Kotlin docs表示支持higher-order functions。当将顶级函数作为参数传递时,为什么语言甚至需要::function语法?

鉴于:

fun isOdd(x: Int) = x % 2 != 0
val numbers = listOf(1, 2, 3)
println(numbers.filter(::isOdd)) // here.

为什么不

fun isOdd(x: Int) = x % 2 != 0
val numbers = listOf(1, 2, 3)
println(numbers.filter(isOdd)) // simple and makes more sense

有关function reference syntax here的更多信息。

2 个答案:

答案 0 :(得分:6)

因为Java(以及Kotlin)对字段和方法使用单独的命名空间,所以需要::来避免歧义。例如:

val isOdd : (Int) -> Boolean = { x -> x % 2 != 0 }
fun isOdd(x: Int): Boolean {
    return x % 2 != 0
}

val odds = listOf(1,2,3).filter(isOdd) // uses the val version
val otherOdds = listOf(1,2,3).filter(::isOdd) // uses the fun version

答案 1 :(得分:6)

Kotlin语言设计试图避免模糊的情况,其中某些东西的缺失可能同时是正确的和不正确的语法。例如,如果您允许使用建议的语法:

isOdd     // error, function invocation expected isOdd(...)
isOdd     // not error, you have a function reference

::是关于意图的明确信号。因此,isOdd案例只会出现错误,因为您现在有可能不重叠:

isOdd      // error, function invocation expected isOdd(...)
::isOdd    // function reference
isOdd()    // error, missing parameter x
isOdd(x)   // function call

这就是Kotlin避免导致模糊状态的原因。您的眼睛也可以快速解决问题,就像IDE和静态分析一样,就像编译器一样。如果你开始允许这种更宽松的语法,你将开始遇到复杂的歧义,例如当使用中缀函数等时。语言设计比#34更复杂哦,让我们让它们输入更少的字符"因为复杂性矩阵比你想象的要大得多,如果你只看一个忽略所有其他用例的用例。

为什么上面接受的答案不正确:

目前接受的答案是这是一个命名空间问题,这是不正确的。在该样本中,他们使用:

val isOdd : (Int) -> Boolean = { x -> x % 2 != 0 }

并声称由于命名空间而无法使用::。它实际上是有效的,因为它已经是一个函数引用并被声明为作为函数引用,因此不需要运算符使其成为函数引用。但是,该功能不是参考。这是一个功能。它需要一个运算符::将其转换为对函数的引用,这是将filter方法用作谓词时所需的函数。

该答案中的主张具有误导性和不真实性。