2014-10-29 29 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