如何在Swift中自定义三元运算符

时间:2014-10-29 18:17:23

标签: ios swift

我知道如何自定义二元运算符,比如

infix operator ** { associativity left precedence 170 }
func ** (left: Double, right: Double) -> Double {
    return pow(left, right)
}

但是,如何在Swift中自定义三元运算符?谁能给我一些想法?非常感谢!

3 个答案:

答案 0 :(得分:18)

实际上可以通过声明两个单独的运算符来协同工作,并为其中一个运算符使用curried函数。

让我们声明一个三元运算符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()
}

这里的重要部分是这个函数是curry - 如果你只用前两个参数调用它,而不是返回T值,它返回一个(left: Bool) -> T函数。这成为我们第一个运算符的函数的第二个参数:

func +-<I: SignedIntegerType, T>(lhs: I, rhs: (left: Bool) -> T) -> T {
    return rhs(left: lhs >= 0)
}

现在我们可以使用我们的&#34;三元&#34;运营商,像这样:

for i in -1...1 {
    let sign = i +- "" +|- "-"
    println("\(i): '\(sign)'")
}
// -1: '-'
// 0: ''
// 1: ''

注意:我用另一个例子写了blog post on this subject

答案 1 :(得分:6)

_ ? _ : _等“真正的”三元运算符需要语言支持。 Swift只允许创建和自定义一元和二元运算符。

您可以在@ NateCook的答案中使用该技术来制作一对二元运算符,它们像三元运算符一样工作,但它们仍然是独立的二元运算符 - 您可以单独使用它们。 (相比之下,_ ? _ : _ 一个三元运算符; _ ? __ : _不能单独使用。)

当然,为何停在那里?您可以链接更多二元运算符以创建四元运算符,依此类推。如需额外的功劳,请尝试让自己成为一名扩展的宇宙飞船运营商:

let c: String = a <=> b
    |<| "a < b"
    |=| "a = b"
    |>| "a > b"

(...但请仅将此作为学术练习,或者使用您编写的代码的任何其他人都会讨厌您。)

答案 2 :(得分:1)

这是您在Swift 4中如何执行的操作:

precedencegroup SecondaryTernaryPrecedence {
    associativity: right
    higherThan: TernaryPrecedence
    lowerThan: LogicalDisjunctionPrecedence
}

infix operator ~ : SecondaryTernaryPrecedence

func ~ <T>(lhs: @autoclosure () -> Bool, rhs: @escaping @autoclosure () -> T) -> (Bool, () -> T) {
    return (lhs(), rhs)
}

infix operator >< : TernaryPrecedence

@discardableResult func >< <T>(lhs: (Bool, () -> T), rhs: @escaping @autoclosure () -> T) -> T {
    if lhs.0 {
        return lhs.1()
    } else {
        return rhs()
    }
}

用法

let n = false ~ "it was true" >< "it was false" //"it was false"

true ~ print("it was true") >< print("it was false")
// Prints "it was true"
                                                                                                                  //