=> A
является ленивым параметром. Он будет оцениваться при упоминании в функции. Это может быть функция, производящая значение или просто значение.
Основное различие между одним и несколькими списками параметров, как в вашем примере:
def measure[A](histogram: Histogram)(thunk: ⇒ A)
def measure[A](histogram: Histogram, thunk: ⇒ A)
(не учитывая implicits и умозаключений типа), как вы применить функцию:
scala> def f[A](i: Int)(p: => A): A = { p }
f: [A](i: Int)(p: => A)A
scala> f(1)(2)
res0: Int = 2
scala> f(1){ println("something") }
something
scala> f(1){
| println("test")
| }
test
scala> def f2[A](i: Int, p: => A): A = { p }
f2: [A](i: Int, p: => A)A
scala> f2(1, 2)
res4: Int = 2
scala> f2(1, println("test"))
test
scala> f2(1, { println("test") })
test
Смотри, что f
с несколькими списками параметров позволяет нам писать в этом стиле: f(...){...}
, а f2
- немного менее изящный, если у вас есть многострочный код в качестве второго аргумента: f(..., {...})
.
Кроме того, если вы делаете много в карирования/частичного применения затем f2
немного легче иметь дело с чем f
:
scala> val f_withFirstArg = f(1) _
f_withFirstArg: (=> Nothing) => Nothing = <function1>
scala> val f2_withFirstArg = f2(1, _)
<console>:8: error: missing parameter type for expanded function ((x$1) => f2(1, x$1))
val f2_withFirstArg = f2(1, _)
^
Мы должны указать параметр типа явно, определение типа не может коротко:
scala> val f2_withFirstArg = f2(1, _: String)
f2_withFirstArg: String => String = <function1>
Если вы хотите получить техническую информацию об этом, то стоит отметить, что они фактически имеют другой тип:
scala> :type f _
Int => ((=> Nothing) => Nothing)
scala> :type f2 _
(Int, => Nothing) => Nothing
f
- это функция, которая принимает Int
и возвращает другую функцию, которая принимает тип A
и будет производить тип A
. f2
- это функция, которая принимает 2 аргумента: Int
и A
и возвращает A
.
Это действительно зависит от вашего кода. Если вам нужно сделать много частичного приложения или нужно меньше аннотации из-за недостатков вывода типа, используйте несколько списков параметров. В противном случае нет необходимости слишком усложнять ситуацию и использовать обычные функции списка параметров.
Наконец, вы всегда можете конвертировать из одного типа функции к другой до тех пор, как это имеет смысл:
scala> f2 _
res13: (Int, => Nothing) => Nothing = <function2>
scala> f2 _ curried
warning: there were 1 feature warning(s); re-run with -feature for details
res14: Int => ((=> Nothing) => Nothing) = <function1>
scala> f _ curried
<console>:9: error: value curried is not a member of Int => ((=> Nothing) => Nothing)
f _ curried
^
scala> f _ tupled
<console>:9: error: value tupled is not a member of Int => ((=> Nothing) => Nothing)
f _ tupled
^
scala> f2 _ tupled
warning: there were 1 feature warning(s); re-run with -feature for details
res17: ((Int, => Nothing)) => Nothing = <function1>
Обратите внимание, что мы не можем сделать f
выделанной, потому что уже есть. Мы не можем сделать f
, потому что это ничего не изменит. Тем не менее, мы можем преобразовать f2
в f
с помощью curried
:
scala> :type f _
Int => ((=> Nothing) => Nothing)
scala> :type f2 _ curried _
Int => ((=> Nothing) => Nothing)
В 1-м, два аргумента кэрри, во 2-ом они не являются. Что вы пытаетесь изучить/решить? – jwvh
@jwvh Что польза от каррирования против альтернативы? Спасибо за ответ! – Shehaaz
@jwvh Я вижу, что вы можете частично вызвать функцию с currying. http://docs.scala-lang.org/tutorials/tour/currying.html – Shehaaz