2015-07-03 75 views
4

爲什麼這會產生一個錯誤,它應該如何寫入?Swift三元運算符編譯錯誤

let x = 5 
    let y = 4 
    var z:Int 
    x < 4 ? z = 6 : z = 8 

的錯誤是「找不到<接受所提供的參數過載」

+6

@ LeoDabus的答案是正確的,但僅僅是明確的,爲什麼你選擇不工作的原因是因爲各個運營商的優先級。三元運算符不必解析爲表達式:它也可以只是語句。 'x <4? (z = 6):(z = 8)'例如,將工作。 – oisdk

+1

@oisdk:請把你的評論變成一個答案,因爲這值得我的讚賞。從來沒有意識到三元操作可以這樣使用。 – Antonio

回答

7

原因您的三元運算符不工作有原因的優先級的各種中綴操作員。 You can see the operator precedence list here.如果你看,你會發現底層的操作員通常放置在較大的代碼塊之間。優先級越高,它越緊緊地將表達式限制在其左側(或右側)。所以,你通常希望你=運營商有一個非常低的相關性,所以在這樣的表達式:

let x = 2 + 3 

+會搶了兩個操作數在它兩側=會,所以它解析於:

let x = (2 + 3) 

,而不是像這樣:

(let x = 2) + 3 

哪個更不合理。

三元有條件的經營者有100優先級,而=經營者有90優先所以在你的榜樣,當你有這樣的:

x < 4 ? z = 6 : z = 8 

的關聯性是這樣的:

x... 
x < ... 
x < 4 // precedence 130, so resolves 
(x < 4)... 
(x < 4) ?... 
(x < 4) ? z... 
(x < 4) ? z = ... // Does not yet resolve. Why? Well, here, the ternary isn't 
        // really an infix. It is special kind of operator that 
        // takes something between ? and :. So normal associativity 
        // doesn't apply. (I'm still experimenting...) 
(x < 4) ? z = 6 : ... 
(x < 4) ? z = 6 : z // HERE it resolves. The z is grabbed, as the ternary has 
        // precedence 100, larger than the 90 precedence of the = 
((x < 4) ? z = 6 : z) = 8 

因此,由於三元運算符的優先級高於賦值運算符的優先級,它會「抓取」z,然後當它找到=時,它會全部混淆。什麼編譯器看到看起來是這樣的:

if (x < 4) { z = 6 } else { z } = 8... // Compiler has a hissy fit 

那麼如何解決這個問題?

x < 4 ? (z = 6) : (z = 8) // x < 4 ? z = 6 : (z = 8) works as well 

括號使關聯明確。爲什麼它首先以這種方式工作?那麼,通常你使用三元運算符來解決它的表達式(就像在@LeoDabus的答案中)。而在這種情況下,其關聯性意味着你需要括號:

let z = x < 4 ? 6 : 8 
let z... 
let z = ... 
let z = x ... 
let z = x < 4 // < has precedence 130, bigger than = 
let z = (x < 4) ? // ? has precedence of 100, bigger than = 
let z = if (x < 4) { 6 } else { 8 } 

我希望幫助,並很有意義。 (我可能得到了一些我的優先解釋錯誤,我發現它很混亂)

原來,我確實得到了一些我的優先解釋錯了。如果我的解釋是正確的,這個就不用工作:

x < 4 ? z = 6 : (z = 8) 

但它確實!事實證明,優先級問題發生在之後之後,而不是之前。(我在上面解釋一下)

另外,實際的帶花括號的if語句並不是解析爲表達式。所以這不起作用:

let z = if (x < 4) { 6 } else { 8 } 
1
let x = 5 
let y = 4 
let z = x < 4 ? 6 : 8