Swift Ternary Syntax Error

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

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

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 }

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
}

Using ternary operator in SwiftUI causes mismatching types error, why?

Besides what @Don said about the extra ), CinderDarkButtonStyle and CinderLightButtonStyle are different structs. They aren't the same type.

What you can do is make a custom function that returns an opaque type, as said in this answer. Try something like this:

struct ContentView: View {
@State var colorScheme = ColorScheme.dark

var body: some View {
GeometryReader { geometry in
Button("Create Account", action: {
//DO SOME ACTION
})
.buttonStyle(for: colorScheme, geometry: geometry) /// use custom buttonStyle function
}
}
}

extension Button {
@ViewBuilder
func buttonStyle(for colorScheme: ColorScheme, geometry: GeometryProxy) -> some View {
switch colorScheme {
case .light:
buttonStyle(CinderDarkButtonStyle(geometry: geometry))
case .dark:
buttonStyle(CinderLightButtonStyle(geometry: geometry))
}
}
}

The above switches between a buttonStyle(CinderDarkButtonStyle(geometry: geometry)) and buttonStyle(CinderLightButtonStyle(geometry: geometry)) modifier, based on the colorScheme.

Why is the let variable = x syntax not working with the ternary operator?

if let is a special Swift form that allows you to rebind an identifier while unwrapping an Optional. A let statement by itself can't rebind an identifier declared in the same scope. Them's the rules.

Furthermore, you cannot use an Optional as if it were a BooleanType, which you're trying to do (since the conditional of ?: has to be a BooleanType).

Also note that print returns () (the empty tuple, also known as the singleton instance of the Void type). So there's no reason to rebind foo to the return value of print.

This works, though it's not good style:

foo != nil ? print("set") : print("nil")

This is good style:

if foo != nil {
print("set")
} else {
print("nil")
}

Or this:

print(foo != nil ? "set" : "nil")

The following is worse in this case, but is a reasonable pattern when you need to transform the wrapped value if set, and provide a default if nil:

print(foo.map { _ in "set" } ?? "nil" )

If you just want to unwrap foo for use later in the function, without increasing the brace nesting level, you can use guard:

guard let foo = foo else {
print("nil")
return // you must return or throw or abort here in a guard statement
}

// Here foo has been rebound and is no longer optional.
print("set to \(foo)")

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