Полезность (как в практических приложениях) Curry v.s. Частичное применение в Scala - PullRequest
51 голосов
/ 09 ноября 2011

Я пытаюсь понять преимущества каррирования над частичными приложениями в 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)

Итак, если я могу легко вычислить частично примененную функцию, каковы преимущества каррирования?

Ответы [ 2 ]

97 голосов
/ 09 ноября 2011

Каррирование в основном используется, если второй раздел параметров является функцией или параметром по имени.Это имеет два преимущества.Сначала аргумент функции может выглядеть как блок кода, заключенный в фигурные скобки.Например,

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

Это читается лучше, чем альтернатива без ускорения:

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

Во-вторых, и, что более важно, вывод типа обычно может определить тип параметра функции, поэтому он не долженбудет дан на сайте вызова.Например, если я определяю 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)

Если последний параметр не является функцией илиИмя параметра я бы не советовал каррировать._ Нотация Scala является не только легкой, но и более гибкой и понятной для IMO.

6 голосов
/ 09 ноября 2011

Я думаю, это станет понятнее, если вы перевернете свой пример с карри:

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

val d = sum4(2, 2) { x =>
  x * x
}

Это скорее оптический эффект, но вам не нужно использовать круглые скобки вокруг всего выражения.Конечно, вы можете достичь того же результата, используя частичное приложение или создав вспомогательный метод для инвертирования аргументов.Дело в том, что вам не нужно делать все это, если вы сначала начинаете с метода с карри.В этом смысле карри - это скорее API и синтаксис.Не ожидается, что вы используете

val partial_sum4 = sum4(2, 2)

где-либо в вашем коде или что это каким-либо образом особенно важно сделать.Просто вы легко получаете красивое выражение.

(Ну, и есть некоторые преимущества в отношении вывода типов…)

...