在Scala中,我可以使用两个参数列表定义一个函数.
def myAdd(x :Int)(y :Int) = x + y
Run Code Online (Sandbox Code Playgroud)
这样可以轻松定义部分应用的功能.
val plusFive = myAdd(5) _
Run Code Online (Sandbox Code Playgroud)
但是,我可以通过定义和返回嵌套函数来完成类似的事情.
def myOtherAdd(x :Int) = {
def f(y :Int) = x + y
f _
}
Run Code Online (Sandbox Code Playgroud)
在化妆方面,我已经移动了下划线,但这仍然感觉像是在晃动.
val otherPlusFive = myOtherAdd(5)
Run Code Online (Sandbox Code Playgroud)
我应该使用什么标准来偏好一种方法呢?
至少有四种方法可以完成同样的事情:
def myAddA(x: Int, y: Int) = x + y
val plusFiveA: Int => Int = myAddA(5,_)
def myAddB(x: Int)(y : Int) = x + y
val plusFiveB = myAddB(5) _
def myAddC(x: Int) = (y: Int) => x + y
val plusFiveC = myAddC(5)
def myAddD(x: Int) = {
def innerD(y: Int) = x + y
innerD _
}
val plusFiveD = myAddD(5)
Run Code Online (Sandbox Code Playgroud)
您可能想知道哪个是最有效的,哪个是最好的风格(对于一些基于非绩效的最佳衡量标准).
就效率而言,事实证明所有四个基本上是等价的.前两种情况实际上发出完全相同的字节码; JVM对多个参数列表一无所知,所以一旦编译器计算出来(你需要在案例A上使用类型注释来帮助它),它就完全相同了.第三种情况也非常接近,但由于它预先承诺返回一个函数并在现场指定它,它可以避免一个内部字段.第四种情况与前两种情况完全相同; 它只是转换到Function1方法内部而不是外部.
在风格方面,我建议B和C是最好的方法,取决于你在做什么.如果您的主要用例是创建一个函数,而不是使用两个参数列表就地调用,那么使用C,因为它会告诉您它将要执行的操作.(例如,这个版本对于来自Haskell的人来说也特别熟悉.)另一方面,如果你大部分时间都要调用它,但只是偶尔会把它称之为咖喱,那么就用B.再说一遍,它更清楚地说明了什么它应该做到.
你也可以这样做:
def yetAnotherAdd(x: Int) = x + (_: Int)
Run Code Online (Sandbox Code Playgroud)
您应该根据意图选择API.Scala中有多个参数列表的主要原因是帮助进行类型推断.例如:
def f[A](x: A)(f: A => A) = ...
f(5)(_ + 5)
Run Code Online (Sandbox Code Playgroud)
人们也可以使用它来拥有多个varargs,但我从未见过这样的代码.而且,当然,需要隐式参数列表,但这是另一回事.
现在,有许多方法可以让函数返回函数,这几乎就是currying的作用.你应该使用它们,如果API 应该被看作是一个返回函数的函数.
我认为很难比这更精确.
| 归档时间: |
|
| 查看次数: |
1801 次 |
| 最近记录: |