咖喱,这就是为什么
Daniel 在解释为什么需要无参数方法方面做得很好。我将解释为什么将它们与零参数方法区别开来。
许多人将无参数函数和零参数函数之间的区别视为某种模糊形式的语法糖。事实上,它纯粹是 Scala 如何支持柯里化的产物(为了完整起见,请参阅下文,以更全面地解释柯里化是什么,以及为什么我们都这么喜欢它)。
形式上,一个函数可以有零个或多个参数列表,每个参数列表有零个或多个参数。
这意味着以下内容是有效的:def a
, def b()
,还有人为的def c()()
等等def d(x: Int)()()(y: Int)
......
一个函数def foo = ???
有零个参数列表。一个函数def bar() = ???
只有一个参数列表,参数为零。引入将这两种形式混为一谈的附加规则会破坏柯里化作为一种一致的语言特征:def a
在形式上等同于def b()
和def c()()
两者;def d(x: Int)()()(y: Int)
将等同于def e()(x: Int)(y: Int)()()
。
一种与柯里化无关的情况是在处理 Java 互操作时。Java 不支持柯里化,因此为像"test".length()
(直接调用java.lang.String#length()
)这样的零参数方法引入语法糖也可以调用为"test".length
.
柯里化的快速解释
Scala 支持一种名为“currying”的语言特性,以数学家 Haskell Curry 命名。
Currying 允许您使用多个参数列表定义函数,例如:
def add(a: Int)(b: Int): Int = a + b
add(2)(3) // 5
这很有用,因为您现在可以inc
根据 的部分应用来定义add
:
def inc: Int => Int = add(1)
inc(2) // 3
柯里化通常被视为通过库引入控制结构的一种方式,例如:
def repeat(n: Int)(thunk: => Any): Unit = (1 to n) foreach { _ => thunk }
repeat(2) {
println("Hello, world")
}
// Hello, world
// Hello, world
回顾一下,看看如何repeat
打开另一个使用柯里化的机会:
def twice: (=> Any) => Unit = repeat(2)
twice {
println("Hello, world")
}
// ... you get the picture :-)