I would like to be able to use if-let in a similar fashion to the commonly used if-else shorthand: <condition> ? <expression1> : <expression2>
. This syntax would look something like this:
<let condition creating variable v1> ? <expression using v1> : <expression not using v1>
Here is an example of how this syntax might look (doesn't compile):
let name: String? = getName()
var dict: [String: String]? = let name = name ? ["name": name] : nil
The multi-line equivalent that I know is possible is the following:
let name: String? = getName()
var dict: [String: String]?
if let name = name {
dict = ["name": name]
} else {
dict = ["error": "no name"]
}
but even with this multi-line example, the dict has to be a var
, whereas the one liner shorthand could be assigned to a let
constant.
Is there any existing syntax that will accomplish this if-let shorthand? If there isn't is there any reason that Swift doesn't implement this syntax already?
Thanks!
CodePudding user response:
You can write this using map
:
let dict = getName().map { name in ["name": name] } ?? ["error": "no name"]
The closure parameter is <let condition creating variable v1>
, and the closure's return value is the <expression using v1>
. x.map
returns nil when x
is nil, so the thing after ??
corresponds to the <expression not using v1>
.
Instead of { name in ["name": name] }
, you can also shorten it to { ["name": $0] }
.
Note that the dict
in the "multiline version" can be declared as a let
:
let dict: [String: String]
if let name = getName() {
dict = ["name": name]
} else {
dict = ["error": "no name"]
}
The compiler is smart enough to see that each branch of the if statement is mutually exclusive, and one of the branches must be executed, so you are not reassigning a let
.