Scala中Currying vs Partial Application的实用性(如实际应用)

Hug*_*ira 52 scala currying partial-application

我试图了解在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)
Run Code Online (Sandbox Code Playgroud)

那么,如果我可以轻松计算部分应用的功能,那么currying的优点是什么?

Mar*_*sky 98

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

using(new File(name)) { f =>
  ...
}
Run Code Online (Sandbox Code Playgroud)

这比未经证实的替代方案更好:

using(new File(name), f => {
  ...
})
Run Code Online (Sandbox Code Playgroud)

其次,更重要的是,类型推断通常可以找出函数的参数类型,因此不必在调用站点给出.例如,如果我max在这样的列表上定义一个函数:

def max[T](xs: List[T])(compare: (T, T) => Boolean)
Run Code Online (Sandbox Code Playgroud)

我可以这样称呼它:

max(List(1, -3, 43, 0)) ((x, y) => x < y)
Run Code Online (Sandbox Code Playgroud)

甚至更短:

max(List(1, -3, 43, 0)) (_ < _)
Run Code Online (Sandbox Code Playgroud)

如果我定义max为一个未经证实的函数,这将无法工作,我必须这样称呼它:

max(List(1, -3, 43, 0), (x: Int, y: Int) => x < y)
Run Code Online (Sandbox Code Playgroud)

如果最后一个参数不是函数或按名称参数,我不会建议currying.Scala的_意思是轻量级,更灵活,IMO更清晰.


Deb*_*ski 6

如果你颠倒你的咖喱例子,我认为会更清楚:

def sum4(a: Int, b: Int)(f: Int => Int): Int = f(a) + f(b)

val d = sum4(2, 2) { x =>
  x * x
}
Run Code Online (Sandbox Code Playgroud)

它更像是一种光学效果,但你不需要在整个表达式周围使用任何括号.当然,您可以使用部分应用程序或通过创建辅助方法来反转参数来实现相同的结果.关键是,如果你首先从一个咖喱方法开始,你不必完成所有这些.从这个意义上讲,currying更多的是API和语法糖.预计您不会使用

val partial_sum4 = sum4(2, 2)
Run Code Online (Sandbox Code Playgroud)

代码中的任何地方或者这在任何方面都特别有意义.只是你很容易得到一个漂亮的表情.

(嗯,类型推断有一些优点......)