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