何时使用 Currying

Currying 是一种翻译函数求值的技术,该函数将多个参数计算为一系列函数,每个函数都有一个参数

例如,这通常很有用:

  1. 函数的不同参数在不同时间计算。 (例 1)
  2. 函数的不同参数由应用程序的不同层计算。 (例 2)

例 1

我们假设年收入总额是由收入和奖金组成的函数:

val totalYearlyIncome:(Int,Int) => Int =  (income, bonus) => income + bonus

以上 2-arity 函数的 curried 版本是:

val totalYearlyIncomeCurried: Int => Int => Int = totalYearlyIncome.curried

请注意,在上面的定义中,类型也可以被视为/写为:

Int => (Int => Int)

我们假设年收入部分是事先知道的:

val partialTotalYearlyIncome: Int => Int = totalYearlyIncomeCurried(10000)

在某些方面,奖金是已知的:

partialTotalYearlyIncome(100)

例 2

让我们假设汽车制造涉及车轮和车身的应用:

val carManufacturing:(String,String) => String = (wheels, body) => wheels + body

这些部件由不同的工厂应用:

class CarWheelsFactory {
  def applyCarWheels(carManufacturing:(String,String) => String): String => String =
          carManufacturing.curried("applied wheels..")
}
    
class CarBodyFactory {
  def applyCarBody(partialCarWithWheels: String => String): String = partialCarWithWheels("applied car body..")
}

请注意,上面的 CarWheelsFactory 会影响汽车的制造功能并仅适用于车轮。

然后汽车制造过程将采用以下形式:

val carWheelsFactory = new CarWheelsFactory()
val carBodyFactory   = new CarBodyFactory()

val carManufacturing:(String,String) => String = (wheels, body) => wheels + body
  
val partialCarWheelsApplied: String => String  = carWheelsFactory.applyCarWheels(carManufacturing)
val carCompleted = carBodyFactory.applyCarBody(partialCarWheelsApplied)