Ответ 1
Несколько методов списка параметров
Для вывода типа
Методы с несколькими разделами параметров могут использоваться для поддержки локального ввода типа, используя параметры в первом разделе для вывода аргументов типа, которые будут предоставлять ожидаемый тип аргумента в следующем разделе. foldLeft
в стандартной библиотеке является каноническим примером этого.
def foldLeft[B](z: B)(op: (B, A) => B): B
List("").foldLeft(0)(_ + _.length)
Если это было написано так:
def foldLeft[B](z: B, op: (B, A) => B): B
Можно было бы указать более явные типы:
List("").foldLeft(0, (b: Int, a: String) => a + b.length)
List("").foldLeft[Int](0, _ + _.length)
Для свободного API
Другое использование нескольких методов разделов параметров - это создание API, который выглядит как языковая конструкция. Вызывающий может использовать скобки вместо круглых скобок.
def loop[A](n: Int)(body: => A): Unit = (0 until n) foreach (n => body)
loop(2) {
println("hello!")
}
Применение списков N аргументов к методу с разделами параметров M, где N < M, можно явно преобразовать в функцию с помощью < <25 > или неявно с ожидаемым типом FunctionN[..]
. Это функция безопасности, см. Примечания об изменении для Scala 2.0 в Scala Ссылки для фона.
Выполненные функции
Сбрасываемые функции (или просто функции, возвращающие функции) легче применить к N спискам аргументов.
val f = (a: Int) => (b: Int) => (c: Int) => a + b + c
val g = f(1)(2)
Это небольшое удобство иногда стоит. Обратите внимание, что функции не могут быть параметрическими, но в некоторых случаях требуется метод.
Второй пример - это гибрид: метод с одним параметром, который возвращает функцию.
Многоэтапное вычисление
Где еще используются карриные функции? Здесь шаблон, который появляется все время:
def v(t: Double, k: Double): Double = {
// expensive computation based only on t
val ft = f(t)
g(ft, k)
}
v(1, 1); v(1, 2);
Как мы можем поделиться результатом f(t)
? Общим решением является предоставление векторизованной версии v
:
def v(t: Double, ks: Seq[Double]: Seq[Double] = {
val ft = f(t)
ks map {k => g(ft, k)}
}
Гадкий! Мы запутали несвязанные проблемы - вычисляем g(f(t), k)
и отображаем последовательность из ks
.
val v = { (t: Double) =>
val ft = f(t)
(k: Double) => g(ft, k)
}
val t = 1
val ks = Seq(1, 2)
val vs = ks map (v(t))
Мы также можем использовать метод, возвращающий функцию. В этом случае его немного читаем:
def v(t:Double): Double => Double = {
val ft = f(t)
(k: Double) => g(ft, k)
}
Но если мы попытаемся сделать то же самое с методом с несколькими разделами параметров, мы застреваем:
def v(t: Double)(k: Double): Double = {
^
`-- Can't insert computation here!
}