严格来说,这不是一个柯里化函数,而是一个具有多个参数列表的方法,尽管不可否认它看起来像一个函数。
正如您所说,多个参数列表允许使用该方法代替部分应用的函数。(对不起,我使用的一般愚蠢的例子)
object NonCurr {
def tabulate[A](n: Int, fun: Int => A) = IndexedSeq.tabulate(n)(fun)
}
NonCurr.tabulate[Double](10, _) // not possible
val x = IndexedSeq.tabulate[Double](10) _ // possible. x is Function1 now
x(math.exp(_)) // complete the application
另一个好处是,如果第二个参数列表由单个函数或 thunk 组成,您可以使用花括号代替括号,这看起来不错。例如
NonCurr.tabulate(10, { i => val j = util.Random.nextInt(i + 1); i - i % 2 })
相对
IndexedSeq.tabulate(10) { i =>
val j = util.Random.nextInt(i + 1)
i - i % 2
}
或者对于重击:
IndexedSeq.fill(10) {
println("debug: operating the random number generator")
util.Random.nextInt(99)
}
另一个优点是,您可以参考先前参数列表的参数来定义默认参数值(尽管您也可以说在单个列表中不能这样做是一个缺点:)
// again I'm not very creative with the example, so forgive me
def doSomething(f: java.io.File)(modDate: Long = f.lastModified) = ???
最后,在相关帖子的回答中还有其他三个应用程序为什么 Scala 同时提供多个参数列表和每个列表的多个参数?. 我将在这里复制它们,但功劳归于 Knut Arne Vedaa、Kevin Wright 和即兴的。
第一:你可以有多个 var args:
def foo(as: Int*)(bs: Int*)(cs: Int*) = as.sum * bs.sum * cs.sum
...这在单个参数列表中是不可能的。
其次,它有助于类型推断:
def foo[T](a: T, b: T)(op: (T,T) => T) = op(a, b)
foo(1, 2){_ + _} // compiler can infer the type of the op function
def foo2[T](a: T, b: T, op: (T,T) => T) = op(a, b)
foo2(1, 2, _ + _) // compiler too stupid, unfortunately
最后,这是拥有隐式和非隐式参数的唯一方法,implicit
整个参数列表的修饰符也是如此:
def gaga [A](x: A)(implicit mf: Manifest[A]) = ??? // ok
def gaga2[A](x: A, implicit mf: Manifest[A]) = ??? // not possible