SE-0345: `if let` shorthand for shadowing an existing optional variable

+1.

I've been following this proposal for a while, and I've come to the conclusion that this would be a nice improvement to the language. This syntax helps eliminate one of the most common sources of redundancy within Swift, improving the clarity and readability of code. The syntax is easy to learn and remember (if let foo is just short for if let foo = foo), making it easy to use.

One of the things I've seen many people in this thread get hung up on is the fact that if let foo might not make much sense to a beginner. While I think this is a valid concern, it's important to remember that if let foo = foo is already confusing to some beginners. And even if if let foo syntax confuses a beginner, it's not likely to be confused with something else, so there isn't a high chance of misunderstanding code because of this change. It might be worth looking into changing this syntax for Swift 6, but I feel if let foo is the right syntax for Swift 5.

I dislike the idea of requiring a question mark (as in if let foo?), as it would just cause confusion. Why does if let foo? require a question mark while if let foo = foo doesn't? Why isn’t if case let foo? allowed to elide its initializer? Can we use multiple question marks to unwrap multiple levels of optionality? If so, why can't if let foo = bar be used to unwrap multiple levels of optionality? Proponents of if let foo? sometimes point out that this syntax is similar to pattern matching syntax. However, I don't think duplicating that syntax is desirable in this context. Optional unwrapping conditions and pattern matching conditions are different — deliberately so — and the two syntaxes should be distinct to avoid confusion.

I also dislike the idea of creating a new keyword for this operation. Adding a keyword like shadowing or unwrap would just add unnecessary clutter. This community is prone to becoming overly concerned about changes and demanding new keywords/attributes to make these changes as clear as possible. However, it often becomes evident afterwards that these concerns are unfounded and that a feature is just fine on its own. if let foo isn't going to break the language. It might make the learning curve a tiny bit steeper, but it's worth it because it gives us the ability to write less redundant code. if let syntax is hardly the most difficult thing to learn in regard to optionals.

A lot of the criticism of this proposal is based on the concern that new users might be confused by the syntax. However, with Swift being a serious language used by professional programmers, I think it's also worth considering the perspective of advanced users as well. The fact that the language regularly requires the programmer to type someIdentifier = someIdentifier is ridiculous and reduces the clarity of code through its redundancy. Plenty of programmers who don't regularly visit this forum have been clamoring for this feature. Yes, this construct adds some complexity to the language. But Swift is built on the philosophy of progressive disclosure of complexity, not the philosophy of avoiding complexity at all costs.

I agree with the decision not to support if let foo.bar. I think this would be more appropriate for a "member-binding" pattern syntax (aka destructuring syntax, previously discussed here).


Response to @sstahurski

What historical knowledge is required? If you're referring to how if let foo is short for if let foo = foo, remember that syntax is still necessary to write statements like if let firstUser = users.first. The syntax for if let foo = bar is not historical.

Those declarations aren't equivalent though. if let variable = variable, variable would be equivalent to if let variable, variable and if let variable would be equivalent to if let variable = variable.

I'm not sure I'm understanding you correctly. Are you proposing adding this to the language?

postfix operator +
postfix func + (condition: Bool?) -> Bool {
    return condition ?? false
}

I don't see how the + operator makes sense for this operation. + in Swift usually refers to addition and isn't associated with optional unwrapping or booleans at all. Additionally, I don't think ?? false is common enough to warrant a new operator.

Response to @intswift

The proposal examines if unwrap x in its "Alternatives Considered" section and comes to the conclusion that this syntax is less expressive and less explicit than if let x. Do you have any response to what the proposal says?

This response uses a different definition of "exists" from the original claim. @Vinicius_Vendramini is using the word "exists" to mean that an optional variable has a wrapped value. You're using the word "exists" to mean that a variable is defined.

Likewise, you could argue that there is nothing in if let x = x that suggests x will be unwrapped.

I'd argue that

let foo = Optional(42)
if let foo {
    ...
}

is just as clear about shadowing foo as

let foo = Optional(42)
do {
    let foo = 42
    ...
}

. Swift consistently uses let foo to mean "define a new constant named 'foo'", and this new proposal doesn't break that pattern.

Response to @xwu

I don't see why we would need a shorthand for all shadowing. Unwrap-and-shadow is an extremely common pattern, while other kinds of shadowing are much less common and more likely to be confusing.

18 Likes