Swift: как изменить порядок и пропустить параметры в функциях, хранящихся в переменных

Я немного знаком с хранением и передачей функций в 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 { ... }

Это необычно иметь власть перед базой, и скажем, что где 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: { $0 })

Если что-либо из этого возможно, было бы идеально, если бы кто-то мог направить меня к официальной документации, где это объясняется.

1 ответ

Решение

Для вашего случая интерполяции (другие случаи следуют) просто определите следующее:

mathOperation = { interpolate (start: $0, end: $1, by: 0.5, nonlinearity: { $0 })}

По сути вы заверните interpolate в закрытии, где некоторые из аргументов фиксированы, такие как by в 0.5 в этом примере. (Это называется " частичное применение")

Вы также можете обобщить это следующим образом:

func interpolateToMathOperation (by: Double, nonlinearity: @escaping (Double) -> Double) -> (Double, Double) -> Double {
  return { interpolate (start: $0, end: $1, by: by, nonlinearity: nonlinearity)}
}

Выше возвращается mathOperation за interpolate по умолчанию by а также nonlinearity аргументы.

В бою:

  // 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: $0, end: $1, by: by, nonlinearity: nonlinearity)} 
  8. } 
  9> var mathOperation = interpolateToMathOperation (by: 0.25, nonlinearity: { $0 })
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
Другие вопросы по тегам