I'm trying to assign a value to x
from a function f
that takes one parameter (a string) and throws.
The current scope throws so I believe a do
...catch
isn't required.
I'm trying to use try
with the coalescing operator ??
but I'm getting this error: 'try' cannot appear to the right of a non-assignment operator
.
guard let x = try f("a") ??
try f("b") ??
try f("c") else {
print("Couldn't get a valid value for x")
return
}
If I change try
to try?
:
guard let x = try? f("a") ??
try? f("b") ??
try? f("c") else {
print("Couldn't get a valid value for x")
return
}
I get the warning Left side of nil coalescing operator '??' has non-optional type 'String??', so the right side is never used
and the error: 'try?' cannot appear to the right of a non-assignment operator
.
If I put each try? in brackets:
guard let x = (try? f("a")) ??
(try? f("b")) ??
(try? f("c")) else {
print("Couldn't get a valid value for x")
return
}
It compiles but x is an optional and I would like it to be unwrapped.
if I remove the questions marks:
guard let x = (try f("a")) ??
(try f("b")) ??
(try f("c")) else {
print("Couldn't get a valid value for x")
return
}
I get the error Operator can throw but expression is not marked with 'try'
.
I'm using Swift 4.2 (latest in Xcode at time of writing).
What is the correct way to do this to get an unwrapped value in x
?
Update:* f()
's return type is String?. I think the fact that it's an optional string is important.
According to MDN, the nullish coalescing is "a logical operator that returns its right-hand side operand when its left-hand side operand is null or undefined, and otherwise returns its left-hand side operand.".
The JavaScript double question mark (??) operator is called the nullish coalescing operator and it provides a default value when a variable or an expression evaluates to null or undefined.
Since JavaScript returns a boolean value of true when your looking at a variable that is not set to* null* or undefined, you can use the || (or) operator to do null coalescing. Basically, as long as the first value is not null or undefined it's returned, otherwise the second value is returned.
A nullish value is a value that is either null or undefined .
A single try
can cover the entire expression, so you can just say:
guard let x = try f("a") ?? f("b") ?? f("c") else {
print("Couldn't get a valid value for x")
return
}
Same goes for try?
:
guard let x = try? f("a") ?? f("b") ?? f("c") else {
print("Couldn't get a valid value for x")
return
}
Although note that in Swift 4.2 x
will be String?
due to the fact that you're applying try?
to an already optional value, giving you a doubly-wrapped optional which guard let
will only unwrap one layer of.
To remedy this, you could coalesce to nil
:
guard let x = (try? f("a") ?? f("b") ?? f("c")) ?? nil else {
print("Couldn't get a valid value for x")
return
}
But in Swift 5 this is unnecessary due to SE-0230, where try? f("a") ?? f("b") ?? f("c")
will be flattened into a single optional value automatically by the compiler.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With