Swift:如何重新排序和省略存储在变量中的函数中的参数

Swift: How to reorder and omit parameters in functions stored in variables

我对 Swift 中的函数存储和传递有点熟悉,但是我对该语言在这方面的行为有几个具体问题。

假设我们有一个变量函数 MathOperation:

var mathOperation: (Double, Double) -> Double

现在假设我们将其设置为函数 Subtract:

func subtract (minuend: Double, subtrahend: Double) -> Double {
    return minuend - subtrahend
}
mathOperation = subtract

然后我们应该可以用

调用subtract
let result = mathOperation(3, 4.222)

但是,如果我们想传入一个比 mathOperation 声明要求的参数更多或顺序不同的参数怎么办?例如:

func divide (dividend: Double, divisor: Double, roundToInt: Bool = false) -> Double { ... }

如何将 mathOperation 设置为 divide,从而忽略 roundToInt

此外,是否可以重新排列参数?假设我们在无法修改的库中有一个求幂函数:

func exponentiate (power: Double, base: Double) -> Double { ... }

在base之前有power是不常见的,假设使用mathOperation的地方,我们需要像用(base: Double, power: Double)声明的那样调用它。

有没有办法把mathOperation设置成exponentiate,这样调用的时候参数就反转了?

最后一个问题。假设我们有一个插值函数,我们想将 mathOperation 设置为:

func interpolate (start: Double, end: Double, by: Double, nonlinearity: (Double) -> Double) -> Double { ... }

有没有办法将 mathOperation 设置为 interpolate 以便

mathOperation (a, b)

结果

interpolate (start: a, end: b, by: 0.5, nonlinearity: { [=18=] })

如果其中任何一个是可能的,那么如果有人可以指导我找到对此进行解释的官方文档,那将是理想的。

对于您的插值案例(其他案例如下)只需定义以下内容:

mathOperation = { interpolate (start: [=10=], end: , by: 0.5, nonlinearity: { [=10=] })}

本质上,您将 interpolate 包装在一个闭包中,其中一些参数是固定的,例如本例中的 by0.5。 (这称为“partial application”)

您还可以将其归纳为如下内容:

func interpolateToMathOperation (by: Double, nonlinearity: @escaping (Double) -> Double) -> (Double, Double) -> Double {
  return { interpolate (start: [=11=], end: , by: by, nonlinearity: nonlinearity)}
}

给定默认的 bynonlinearity 参数,上面的 returns 一个 mathOperation for interpolate

在行动:

  // Just add - only an example
  1> func interpolate (start: Double, end: Double, by: Double, nonlinearity: (Double) -> Double) -> Double { return start + end }

  6> func interpolateToMathOperation (by: Double, nonlinearity: @escaping (Double) -> Double) -> (Double, Double) -> Double { 
  7.   return { interpolate (start: [=12=], end: , by: by, nonlinearity: nonlinearity)} 
  8. } 
  9> var mathOperation = interpolateToMathOperation (by: 0.25, nonlinearity: { [=12=] })
mathOperation: (Double, Double) -> Double = 0x00000001005ea670 $__lldb_expr15`partial apply forwarder for __lldb_expr_14.(interpolateToMathOperation (by : Swift.Double, nonlinearity : (Swift.Double) -> Swift.Double) -> (Swift.Double, Swift.Double) -> Swift.Double).(closure #1) at repl14.swift

 10> mathOperation(1,2)
$R1: Double = 3