使用以下语法定义启用了柯里化(Currying)的函数时:
def sum(x: Int)(y: Int)(z: Int) = x + y + z
仍然必须为
sum
的柯里化(Currying)调用添加任何调用后缀与 _
:sum _
sum(3) _
sum(3)(2) _
否则编译器会提示。
所以我求助于:
val sum = (x: Int) => (y: Int) => (z: Int) => x + y + z
没有
_
的情况下工作.现在的问题是:为什么多参数列表版本需要
_
为了让 curry 发挥作用?为什么这 2 个版本的语义在所有情况下都不是等效的?另外,后一个版本是否不受欢迎?它有任何警告吗?
最佳答案
这两种语义不同的原因是方法和函数不是一回事。
方法是成熟的 JVM 方法,而函数是值(即 Function1
、Function2
等类的实例)。
所以
def sum(x: Int)(y: Int)(z: Int) = x + y + z
和
val sum = (x: Int) => (y: Int) => (z: Int) => x + y + z
可能看起来相同,但第一个是方法,而第二个是
Function1[Int, Function1[Int, Function1[Int, Int]]]
当您尝试使用需要函数值的方法时,编译器会自动将其转换为函数(称为 eta-expansion 的过程)。
但是,在某些情况下,编译器不会自动对方法进行 eta 扩展,例如您公开的情况,您明确希望部分应用它。
使用
_
触发 eta 扩展,所以一个方法被转换为一个函数,每个人都很高兴。根据 scala 规范,您还可以注释预期的类型,在这种情况下,扩展会自动执行:
def sum(x: Int)(y: Int)(z: Int) = x + y + z
val sumFunction: Int => Int => Int => Int = sum
这也是为什么
def sum(x: Int, y: Int) = x + y
List(1,2,3).reduce(sum)
有效,即我们正在传递一个明确需要函数的方法。
以下是关于 scala 何时执行 eta 扩展的更深入讨论:https://stackoverflow.com/a/2394063/846273
至于选择哪一个,我给你指点this answer ,非常详尽。
关于scala - 在 Scala 中进行柯里化(Currying) : multiple parameter lists vs returning a function,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26161169/