scala - 在 Scala 中进行柯里化(Currying) : multiple parameter lists vs returning a function

标签 scala functional-programming parameter-passing currying

使用以下语法定义启用了柯里化(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 方法,而函数是值(即 Function1Function2 等类的实例)。

所以

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/

相关文章:

scala - 无法使用静态语言创建应用函数?

scala 不会警告未使用的计算或值

java - 在 Java 8 中,如何应用此过滤器?

javascript - 如何在运行相同 GreaseMonkey 用户脚本的 2 个选项卡之间传递信息?

c++ - 什么时候从函数的参数化中省略 const 是安全的?

Scala、JPA 和可为 null 的字段

Scala Seq - 只接受相同子类型的元素

haskell - 默认情况下具有不可变变量的语言,例如 Haskell

javascript - 使用 Ramda 使函数 pointfree

swift - 在可点击的 UIabel 中传递参数