Ответ 1
На самом деле вы можете сделать это, объявив два отдельных оператора, которые работают вместе и используя функцию curries для одного из операторов.
Объявить трехмерный оператор x +- y +|- z
, который будет проверять знак начального значения x
, а затем вернуть второе значение y
, если знак равен нулю или положителен, а окончательное значение z
, если знак является отрицательным. То есть мы должны уметь писать:
let sign = -5 +- "non-negative" +|- "negative"
// sign is now "negative"
Начнем с объявления двух операторов. Важная роль состоит в том, чтобы иметь более высокий приоритет для второго оператора - мы сначала оценим эту часть и вернем функцию:
infix operator +- { precedence 60 }
infix operator +|- { precedence 70 }
Затем определим функции - сначала определим второй:
func +|-<T>(lhs: @autoclosure () -> T, rhs: @autoclosure () -> T)(left: Bool) -> T {
return left ? lhs() : rhs()
}
Важная часть здесь заключается в том, что эта функция является curried - если вы вызываете ее только с помощью первых двух параметров, вместо возвращения значения T
она возвращает функцию (left: Bool) -> T
. Это становится вторым параметром функции для нашего первого оператора:
func +-<I: SignedIntegerType, T>(lhs: I, rhs: (left: Bool) -> T) -> T {
return rhs(left: lhs >= 0)
}
И теперь мы можем использовать наш "троичный" оператор, например:
for i in -1...1 {
let sign = i +- "" +|- "-"
println("\(i): '\(sign)'")
}
// -1: '-'
// 0: ''
// 1: ''
Примечание: Я написал сообщение в блоге по этому вопросу с другим примером.