Ответ 1
Строго говоря, это не валютная функция, а метод с несколькими списками аргументов, хотя, по общему признанию, он выглядит как функция.
Как вы сказали, списки множественных аргументов позволяют использовать этот метод вместо частично применяемой функции. (Извините за обычные глупые примеры, которые я использую)
object NonCurr {
def tabulate[A](n: Int, fun: Int => A) = IndexedSeq.tabulate(n)(fun)
}
NonCurr.tabulate[Double](10, _) // not possible
val x = IndexedSeq.tabulate[Double](10) _ // possible. x is Function1 now
x(math.exp(_)) // complete the application
Другим преимуществом является то, что вы можете использовать фигурные скобки вместо круглых скобок, которые выглядят хорошо, если второй список аргументов состоит из одной функции или thunk. Например.
NonCurr.tabulate(10, { i => val j = util.Random.nextInt(i + 1); i - i % 2 })
против
IndexedSeq.tabulate(10) { i =>
val j = util.Random.nextInt(i + 1)
i - i % 2
}
Или для thunk:
IndexedSeq.fill(10) {
println("debug: operating the random number generator")
util.Random.nextInt(99)
}
Еще одно преимущество: вы можете ссылаться на аргументы предыдущего списка аргументов для определения значений аргументов по умолчанию (хотя вы также можете сказать, что это недостаток, который вы не можете сделать в одном списке:)
// again I'm not very creative with the example, so forgive me
def doSomething(f: java.io.File)(modDate: Long = f.lastModified) = ???
Наконец, есть еще три приложения в ответ на связанный пост Почему Scala предоставляет как список нескольких параметров, так и несколько параметров для списка?. Я просто скопирую их здесь, но это заслуга Кнута Арне Веды, Кевина Райт и extempore.
Во-первых: вы можете иметь несколько аргументов var:
def foo(as: Int*)(bs: Int*)(cs: Int*) = as.sum * bs.sum * cs.sum
... что невозможно в одном списке аргументов.
Во-вторых, это помогает сделать вывод типа:
def foo[T](a: T, b: T)(op: (T,T) => T) = op(a, b)
foo(1, 2){_ + _} // compiler can infer the type of the op function
def foo2[T](a: T, b: T, op: (T,T) => T) = op(a, b)
foo2(1, 2, _ + _) // compiler too stupid, unfortunately
И последнее, это единственный способ, которым вы можете иметь неявные и неявные аргументы, поскольку implicit
является модификатором для всего списка аргументов:
def gaga [A](x: A)(implicit mf: Manifest[A]) = ??? // ok
def gaga2[A](x: A, implicit mf: Manifest[A]) = ??? // not possible