Home > Enterprise >  Is there an if-let one liner shorthand?
Is there an if-let one liner shorthand?

Time:05-10

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.

  • Related