有用性(在实际应用中)柯里与部分应用在斯卡拉

我试图理解在Scala中部分应用程序的优点。 请考虑下面的代码:

def sum(f: Int => Int) = (a: Int, b: Int) => f(a) + f(b) def sum2(f: Int => Int, a: Int, b: Int): Int = f(a) + f(b) def sum3(f: Int => Int)(a: Int, b: Int): Int = f(a) + f(b) val ho = sum({identity}) val partial = sum2({ identity }, _, _) val currying = sum3({ identity }) val a = currying(2, 2) val b = partial(2, 2) val c = ho(2, 2) 

那么,如果我能够很容易地计算部分应用函数,那么currying的优点是什么?

如果第二个参数部分是函数或名称参数,则主要使用Currying。 这有两个好处。 首先,函数参数可以看起来像一个用大括号括起来的代码块。 例如

 using(new File(name)) { f => ... } 

这读起来比不错的select更好:

 using(new File(name), f => { ... }) 

其次,更重要的是,types推断通常可以计算出函数的参数types,所以不需要在调用地点给出。 例如,如果我定义一个像这样的列表的max函数:

 def max[T](xs: List[T])(compare: (T, T) => Boolean) 

我可以这样称呼它:

 max(List(1, -3, 43, 0)) ((x, y) => x < y) 

甚至更短:

 max(List(1, -3, 43, 0)) (_ < _) 

如果我将max定义为一个不安全的函数,这是行不通的,我不得不这样调用它:

 max(List(1, -3, 43, 0), (x: Int, y: Int) => x < y) 

如果最后一个参数不是一个函数或名称参数,我不会build议currying。 斯卡拉的标记是轻量级,更灵活和IMO更清晰。

我认为,如果你把你的咖喱的例子颠倒过来,

 def sum4(a: Int, b: Int)(f: Int => Int): Int = f(a) + f(b) val d = sum4(2, 2) { x => x * x } 

这更多的是光学效果,但是你不需要在整个expression式中使用任何括号。 当然,你可以使用部分应用程序或者通过创build一个辅助方法来颠倒参数来获得相同的结果。 问题是,如果你首先使用咖喱方法,那么你就不必这么做了。 从这个意义上讲,咖喱是一个API和语法糖的东西。 这不是你所期望的

 val partial_sum4 = sum4(2, 2) 

在你的代码中的任何地方,或者这是以任何方式特别有意义的。 这只是你容易得到一个很好看的expression。

(那么,types推断方面有一些优点…)