Scala 中柯里化的两种方式;每个的用例是什么?

2023-12-09

我正在讨论多个参数列表在我维护的 Scala 风格指南中。我开始意识到有两种方法currying,我想知道用例是什么:

def add(a:Int)(b:Int) = {a + b}
// Works
add(5)(6)
// Doesn't compile
val f = add(5)
// Works
val f = add(5)_
f(10) // yields 15

def add2(a:Int) = { b:Int => a + b }
// Works
add2(5)(6)
// Also works
val f = add2(5)
f(10) // Yields 15
// Doesn't compile
val f = add2(5)_

样式指南错误地暗示它们是相同的,而实际上它们显然不同。该指南试图阐述关于创建的柯里化函数的观点,并且,虽然第二种形式不是“按书本”柯里化,但它仍然与第一种形式非常相似(尽管可以说更容易使用,因为你不需要这_)

使用这些表格的人对于何时使用一种表格而不是另一种表格有何共识?


多参数列表方法

对于类型推断

具有多个参数部分的方法可用于辅助本地类型推断,方法是使用第一部分中的参数来推断类型参数,这些参数将为后续部分中的参数提供预期类型。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 _,或隐式地,具有预期类型FunctionN[..]。这是一项安全功能,有关背景信息,请参阅 Scala 参考资料中的 Scala 2.0 更改说明。

柯里化函数

柯里化函数(或者简单地说,返回函数的函数)更容易应用于 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!
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Scala 中柯里化的两种方式;每个的用例是什么? 的相关文章

随机推荐