You can actually do this by declaring two separate operators that work together and using a curried function for one of the operators.
Let's declare a ternary operator x +- y +|- z
that will check the sign of the initial value x
, and then return the second value y
if the sign is zero or positive and the final value z
if the sign is negative. That is, we should be able to write:
let sign = -5 +- "non-negative" +|- "negative"
// sign is now "negative"
We'll start by declaring the two operators. The important part is to have higher precedence on the second operator - we'll evaluate that part first and return a function:
infix operator +- { precedence 60 }
infix operator +|- { precedence 70 }
Then define the functions - we'll define the second first:
func +|-<T>(lhs: @autoclosure () -> T, rhs: @autoclosure () -> T)(left: Bool) -> T {
return left ? lhs() : rhs()
}
The important part here is that this function is curried -- if you only call it with the first two parameters, instead of returning a T
value, it returns a (left: Bool) -> T
function. That becomes the second parameter of the function for our first operator:
func +-<I: SignedIntegerType, T>(lhs: I, rhs: (left: Bool) -> T) -> T {
return rhs(left: lhs >= 0)
}
And now we can use our "ternary" operator, like this:
for i in -1...1 {
let sign = i +- "" +|- "-"
println("(i): '(sign)'")
}
// -1: '-'
// 0: ''
// 1: ''
Note: I wrote a blog post on this subject with another example.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…