为什么Scala中的currying需要多个参数列表?

Cur*_*123 10 scala

假设我有一个我需要部分应用的2个参数的函数,我需要将它定义为:

def f(a: Int)(b: Int) = { /* some code */ }
Run Code Online (Sandbox Code Playgroud)

然后我可以将其部分应用为 def fWithA = f(a) _

我的问题是:为了理解函数,为什么Scala要求使用多个参数列表声明参数?最好能够根据需要调节任何功能.

dre*_*xin 24

实际上,你可以部分应用你想要的任何方法.只需调用方法并省略params:

scala> def foo(a: Int, b: Int) = a*b
foo: (a: Int, b: Int)Int

scala> val x = foo(1,_: Int)
x: Int => Int = <function1>

scala> def bar(x: Int, y: Int, z: Int) = x*y+z
bar: (x: Int, y: Int, z: Int)Int

scala> bar(2,_:Int,6)
res0: Int => Int = <function1>
Run Code Online (Sandbox Code Playgroud)

唯一的区别是,您必须告诉编译器缺少参数的类型,否则它无法在重载方法之间做出决定.

另一种方法,如果你有一个真正的函数,而不是一个方法将调用curried该函数:

scala> val f = {(x:Int, y:Int) => x*y}
f: (Int, Int) => Int = <function2>

scala> f.curried
res2: Int => (Int => Int) = <function1>
Run Code Online (Sandbox Code Playgroud)

您还可以使用以下方法从方法创建函数_:

scala> bar _
res6: (Int, Int, Int) => Int = <function3>
Run Code Online (Sandbox Code Playgroud)

然后呼吁curried:

scala> (bar _).curried
res5: Int => (Int => (Int => Int)) = <function1>
Run Code Online (Sandbox Code Playgroud)


Iul*_*gos 15

"实际"调整的几个原因需要Scala中的多个参数列表:

  • 超载.与纯函数式语言不同,在Scala中,您可以重载方法.如果部分应用函数,编译器可能无法区分您的重载.规范将过载分辨率限制为第一个参数列表.

  • 错误消息."没有足够的方法调用参数"是一个非常有用(且易于理解)的错误消息.如果一个允许curry任何方法,错误消息将是"必需的:但"某些函数类型有许多箭头"类型.

  • 性能.在JVM上运行使调用方法非常有效,而函数(通过接口调用)则更慢.