Swift Ternary Operator Compilation Error

Swift ternary operator compilation error

The reason your ternary operator isn't working there is because of the precedence of the various infix operators. You can see the operator precedence list here. If you look, you'll see that the operators down the bottom are the ones that are usually placed between larger chunks of code. The higher the precedence, the tighter it'll clamp to the expressions to its left (or right). So, you usually want your = operator to have a very low associativity, so in an expression like:

let x = 2 + 3

The + will grab the two operands on either side of it before the = will, so it resolves to:

let x = (2 + 3)

rather than something like:

(let x = 2) + 3

Which makes less sense.

The ternary conditional operator has precedence of 100, whereas the = operator has precedence of 90. So in your example, when you've got this:

x < 4 ? z = 6 : z = 8

The associativity goes like this:

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

So because the precedence of the ternary operator is higher than that of the assignment operator, it "grabs" the z, and then, when it finds the =, it gets all confused. What the compiler sees looks something like this:

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

So how do you fix it?

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

The parentheses make the associativity explicit. Why does it work this way in the first place? Well, usually you use the ternary operator to resolve it to an expression (as was in @LeoDabus' answer). And in that case, its associativity means that you don't need the parentheses:

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 }

I hope that helps, and makes sense. (I might have gotten some of my precedence explanations wrong, I find it quite confusing)

Turns out, I did get some of my precedence explanations wrong. If my explanation had been correct, this wouldn't have worked:

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

But it does! It turns out, the precedence issues happen after the operator, not before. (I explain a bit more above)

Also, the actual if statement with curly braces itself doesn't resolve to an expression. So this doesn't work:

let z = if (x < 4) { 6 } else { 8 }

Why is my Swift ternary operator not working?

The compiler needs a little help, the spaces in your ternary are causing it to get confused due to the way that operator precedence is implemented in the language. If you wrap your statements in parentheses then it will compile and do what you expect.

Also there is property that will allow you to check whether something is a multiple(of:), it can make for easier to read code, though you can use item % 2 == 0 if you wish and it will still work.

var list = [2, 4, 3, 6, 1, 9]

var sumOfEven = 0
var productOfOdd = 1

for item in list {
item.isMultiple(of: 2) ? (sumOfEven += item) : (productOfOdd *= item)
}

print(sumOfEven) // 12
print(productOfOdd) // 27

However, ternaries can make for harder to understand code. This would be better written as an if-else like you had written in your question.

for item in list {
if item % 2 == 0 { // you could use item.isMultiple(of: 2)
sumOfEven += item
} else {
productOfOdd *= item
}
}

Swift ternary syntax error

Swift error messages are frequently cryptic and not helpful. Your real problem is that Swift needs some space around the ? and :.

var topViewIndexForIndexAdjust = ifLeft ? leftTopIndex : rightTopIndex

swift: about ternary operator Question. Why my code is error code??? Please tell me why I'm wrong

In Swift, the ternary condition operator is an expression which takes the form

<condition> ? <expression if true> : <expression if false>

Expressions are part of larger statements, and the ternary specifically is one which evaluates to either the expression after the ?, or the one after the : depending on the truth of the condition.

continue, however, is not an expression but a statement on its own, which means that it cannot be on either side of the ternary.

Thinking about this another way: expressions evaluate to some value (e.g., can be put on the right-hand-side of an assignment, like x = <some expression>), while statements do not (e.g., it doesn't make sense to write x = continue).

You will need to express this in the form of a regular if-statement then:

if arr[a] + arr[b] + arr[c] <= input[1] {
result = arr[a] + arr[b] +arr[c]
} else {
continue
}

Note that the above code might be grammatically correct (in that it will compile), but it is unlikely to be what you mean: the loop will automatically continue at the end of execution even if arr[a] + arr[b] + arr[c] <= input[1] by default, which means that your result may get overwritten later in the loop. It seems likely that you mean something like

outer_loop: for a in 0 ..< arr.count {
for b in 1 ..< arr.count - 1 {
for c in 2 ..< arr.count - 2 {
if arr[a] + arr[b] + arr[c] <= input[1] {
result = arr[a] + arr[b] + arr[c]

// `break` would only exit the `c` loop, but with this label
// we can exit all loops at once.
break outer_loop
}
}
}
}

How to properly use conditionak operator in Swift

I don't know what the warning it but it probably can't figure out the order to apply the operators. This should work.

cell.indentationLevel = indexPath.row == 0 ? kIndentFDA : kIndentCompleted

Ternary operator in Swift Error

Silly. There has to be a space between the BOOL being checked upon and the ?

So flag?expressionA:expressionB won't work.
Instead flag ?expressionA:expressionB will work.

Maybe compiler assumes flag? as optional chaining.

This works

func == (lhs: Employee, rhs: Employee) -> Int {
return (lhs.empName == rhs.empName && lhs.empCode == rhs.empCode) ?1:0
}

Swift's Ternary Conditional Operator returning optional from two non-optional values?

@IBOutlets are defined as implicitly unwrapped optionals - that's what the ! stands for at the end of the type. It still is an optional, but you don't have to explicitly unwrap it when used. You could kind of think about this as a promise to the compiler that although this value could be nil at some point, you will use it responsibly and only after it has been set. When inferring the type for deselectThis, the compiler correctly set it Optional<UIButton>, just without the ! (since ! doesn't change the type per-se in this case).

You can either wrap the whole expression in an if let statement or simply provide the explicitly unwrapped typing by doing var deselectThis: UIButton! = ....

Please note that implicitly unwrapped optionals should be used with care and caution. As always - more in the docs.

Try to return in ternary expression

You should re-write your function like this. This will evaluate the count of the contentPre variable and return the appropriate response.

private func getContentPre(highlight: Highlight) -> String! {
return highlight.contentPre.count == 0 ? ">" : highlight.contentPre
}

However as it would appear that contentPre would be a String you should use .isEmpty as it is more performant that checking the length of a String

private func getContentPre(highlight: Highlight) -> String! {
return highlight.contentPre.isEmpty ? ">" : highlight.contentPre
}


Related Topics



Leave a reply



Submit