2015-07-03 137 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