Scala中每个列表的多个参数列表和多个参数有什么区别?

在Scala中,可以这样写(curried?)函数

def curriedFunc(arg1: Int) (arg2: String) = { ... } 

上面的curriedFunc函数定义与两个参数列表和具有多个参数的函数在单个参数列表中有什么区别:

 def curriedFunc(arg1: Int, arg2: String) = { ... } 

从math的angular度来看,这是(curriedFunc(x))(y)curriedFunc(x,y)但是我可以写def sum(x) (y) = x + ydef sum2(x, y) = x + y

我只知道一个区别 – 这是部分应用function。 但是两种方式对我来说都是相同的。

还有其他的区别吗?

严格地说,这不是一个curried函数,而是一个包含多个参数列表的方法,尽pipe它看起来像一个函数。

正如你所说,多个参数列表允许方法被用于部分应用函数的地方。 (对不起,我使用的通常愚蠢的例子)

 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 } 

或者对于thunk:

 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) = ??? 

最后,还有三个其他应用程序在相关的post的答案为什么斯卡拉同时提供多个参数列表和每个列表多个参数? 。 我只是在这里复制他们,但功劳归功于Knut Arne Vedaa,Kevin Wright和extempore。

首先:你可以有多个variables参数:

 def foo(as: Int*)(bs: Int*)(cs: Int*) = as.sum * bs.sum * cs.sum 

…这在一个参数列表中是不可能的。

其次,它有助于types推断:

 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 

还有另外一个不是0 __的优秀答案 :默认参数。 在另一个参数列表中计算默认值时,可以使用一个参数列表中的参数,但不能使用同一个参数列表中的参数。

例如:

 def f(x: Int, y: Int = x * 2) = x + y // not valid def g(x: Int)(y: Int = x * 2) = x + y // valid 

这就是整个问题,是咖啡和不安全的forms是相同的! 正如其他人所指出的那样,根据具体情况,其中一种或另一种forms在语法上可以更方便地处理,而这是唯一的select。

重要的是要明白,即使Scala没有用于声明curry函数的特殊语法,您仍然可以构build它们; 一旦你有能力创build返回函数的函数,这只是一个math的必然性。

为了演示这个,假设def foo(a)(b)(c) = {...}语法不存在。 那么你仍然可以达到完全一样的东西,如下所示: def foo(a) = (b) => (c) => {...}

像Scala中的许多特性一样,这只是一个语法上的方便,可以做任何事情,但是稍微冗长些。

这两种forms是同构的。 主要区别在于,curry函数更容易部分应用,而非curry函数的语法略好一些,至less在Scala中是这样。