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
Cannot Invoke "+=" with an Argument List of Type (Int, @Value Int)
Is There Difference Between Using a Constructor and Using .Init
Why Do We Need to Specify Init Method
How to Decode Partially Double Serialized JSON String Using 'Codable' Protocol
How to Procedurally Draw Rectangle/Lines in Swift Using Cgcontext
Getting Pixel Format from Cgimage
Animated Curve Line in Swift 3
How to Get String from Ascii Code in Swift
Check If on Correct Dispatch Queue in Swift 3
How to Find a Maximum Value in a Swift Dictionary
How to Convert Unix Timestamp into Swift Nsdate Object
Swift How to Format a Large Number with Thousands Separators
(Cross-)Compiling Swift for Raspberry Pi
Xcode Source Kit Will Not Stop Crashing with Swift
Swift Crash "Exc_Breakpoint 0X0000000... "
Nsattributedstring and Emojis: Issue with Positions and Lengths