scala> def a(i:Int)(j:Int) = i * j
a: (i: Int)(j: Int)Int
scala> def b(i:Int, j:Int) = i * j
b: (i: Int, j: Int)Int
这两个定义非常相似,它们(在我看来)做同样的事情。
除了定义一个接收隐式参数或代码块作为参数的函数外,还有什么理由使用第一个定义样式吗?
答案 0 :(得分:6)
这是我随时编制的列表:
多个参数列表1)类型分辨率
class ResourceManager {
type Resource
def open: Resource = ???
}
class ResourceManagerTest {
// Does not compile: def test1(rm: ResourceManager, r: rm.Resource) = ???
// Compiles: This way the type can be resolved
def test2(rm: ResourceManager)(r: rm.Resource) = ???
}
2)类型推断前面的参数可以“锁定”类型参数以供以后的参数使用(感谢Myserious Dan)
def foo1[A](x: A, f: A => Int) = ???
def foo2[A](x: A)(f: A => Int) = ???
def foo1foo2Demo() {
// This will always demand a type annotation on any anonymous function
// you pass in:
foo1(1, (i: Int) => i * i)
// Does not compile: foo1(1, i => i * i)
// Type not required
foo2(2)(i => i * i)
}
3)类似语法的语言扩展
object MultipleArgumentListsDemo {
// This style of function definition allows syntax-like language extensions
@tailrec
def myWhile(conditional: => Boolean)(f: => Unit) {
if (conditional) {
f
myWhile(conditional)(f)
}
}
def myWhileDemo() {
var count = 0
myWhile(count < 5) {
count += 1
println(count)
}
}
4)同时拥有隐式和非隐式参数,因为implicit是整个参数列表的修饰符:
def f[A](x: A)(implicit mf: Manifest[A]) {
}
5)来自一个参数列表的参数值可用于计算另一个参数列表中的默认值,但不能用于同一个参数列表。
def g(x: Int)(y: Int = x * 2) = {
x + y
}
6)多个重复的参数列表(“varargs”)
def h(as: Int*)(bs: Int*)(cs: Int*) = as.sum * bs.sum * cs.sum
7)部分申请
def i() {
val foop = h(1, 2, 3)(4, 5, 6, 7, 9) _
println(foop(Seq(10, 11)))
}
由于我在编制该列表的过程中没有跟踪我的来源:有可能从其他地方复制了一些或所有示例(其他问题在SO上),所以请删掉一个注释,我将添加引用至于它来自何处。
答案 1 :(得分:3)
以这种方式“currying”功能的主要原因是启用部分应用:
scala> val c = a(5) _
c: Int => Int = <function1>
这里c是一个函数,它接受一个int并返回将该int与5相乘的结果。可能是你在一个方法中设置c,并将它传递给另一个期望函数占用一个Int的方法参数。在这种情况下有点微不足道,但对于一系列用途非常灵活。
答案 2 :(得分:1)
除了支持currying之外,它还有助于类型推断:如果一切都在一个参数列表中,有时编译器无法推断出正确的类型,但是如果你拆分依赖于其他参数绑定的部分,有用。一个典型的例子是foldLeft
:尝试用一个参数列表实现它,然后在某些情况下编译器需要类型注释。