为什么Kotlin需要函数参考语法?

Kotlin docs表示支持高阶函数 。 为什么在将顶级函数作为参数传递时,语言甚至需要一个::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 

更多关于这里的函数参考语法 。

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和静态分析一样,你的眼睛也可以快速地找到问题,就像编译器一样。 如果你开始允许这种宽松的语法,你将开始遇到复杂的模糊,比如当作为中缀函数使用时等等。 语言设计比“哦,让我们让他们输入更少的字符”更复杂,因为复杂度矩阵比你想象的要大得多,如果你只看一个用例而忽略所有其他用例。

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

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

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

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

答案中的主张是误导和不实的。

因为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