2014-10-29 31 views
11

我知道如何自定义二元运算符,这样如何自定义三元运营商在斯威夫特

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

但是,如何在斯威夫特定制三元运营商?任何人都可以给我一些想法吗?非常感谢!

回答

5

“真”三元运算符(如_ ? _ : _)需要语言支持。 Swift允许创建和定制只有一元和二元运算符。

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

当然,为什么要停止呢?您可以链接更多的二元运算符来创建四元运算符,等等。对于额外的信用,尽量让自己的扩展飞船操作:

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

(...但是请只做到这一点作为一个学术活动,或其他任何人谁与代码的工作你写会恨你。)

18

可以实际上通过声明两个单独的运算符一起工作并为其中一个运算符使用curried函数来完成此操作。

让我们来声明一个三元运算符x +- y +|- z,将检查初始值x的符号,然后如果符号是零或正和最终值z如果符号为负返回第二个值y。也就是说,我们应该可以这样写:

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: '' 

注:我写的另一个例子是blog post on this subject

+1

'func + | -'应该也可以使用自动遮挡,以便像通常的'?:'那样懒惰地评估参数。另外,虽然这创建了一个类似于三元运算符的东西,但实际上不能使用'?'和':',因为它们都不是快速有效的'运算符'令牌。 – bames53 2014-10-29 19:35:38

+0

我刚回来做编辑!是的,'?:'本身不能被覆盖。 – 2014-10-29 19:37:39

+0

类似的例子在这里:http://www.reddit.com/r/swift/comments/2fjwav/custom_ternary_operator/ – 2014-10-29 19:47:04