繁体   English   中英

Scala中的Currying:函数中的多个参数,包括类型的匿名函数(=> A)

[英]Currying in Scala: Multiple parameters in a function including an anonymous function of type ( => A)

这两个代码块有什么区别?

def measure[A](histogram: Histogram)(thunk: ⇒ A): A = {
  val start = RelativeNanoTimestamp.now
  try thunk finally {
    val latency = NanoInterval.since(start).nanos
    histogram.record(latency)
}

def measure[A](histogram: Histogram, thunk: ⇒ A): A = {
  val start = RelativeNanoTimestamp.now
  try thunk finally {
    val latency = NanoInterval.since(start).nanos
    histogram.record(latency)
}

Github来源

=> 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(..., {...})

此外,如果你做了很多currying /部分应用,那么f2f更容易处理:

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个参数的函数: IntA并返回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 tupled因为它不会改变任何事情。 但是,我们可以使用curriedf2转换为f

scala> :type f _
Int => ((=> Nothing) => Nothing)

scala> :type f2 _ curried _
Int => ((=> Nothing) => Nothing)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM