`if let x as? T` ↔ `if let x = x as? T`

Now that we have if let x shortcut, shouldn't we also have:

if let value as? T

as a shortcut for

if let value = value as? T

As a small data point – in one of my big projects of all if-let-foos (hundreds of them) about 10% are of the form if-let-foo-as-T.

PS. I also wouldn't mind "if let foo.bar.baz" as a synonym for "if let baz = foo.bar.baz", but let's keep that separate.

10 Likes

Seems reasonable to me -- this was mentioned as a future direction in SE-0345:

A natural extension of this new syntax could be to support shorthand for optional casting. For example:

if let foo as? Bar { ... }

could be equivalent to:

if let foo = foo as? Bar { ... }

This is not included in this proposal, but is a reasonable feature that could be added in the future.

This wasn't included in SE-0345 because it makes the parsing and formal grammar a bit more complicated. I suppose at the time SE-0345 was still somewhat controversial, so there were bigger things to worry about.

In retrospect it seems perhaps a bit confusing to not support this, since it's visually very similar to the supported if let foo = foo case, and the = foo here isn't required for any semantic reason. Are there any other cases like this, that seem superficially related to if let foo = foo but which don't support the shorthand from SE-0345?

6 Likes

Should we still have the question mark after as in this shorthand? There isn't really anything related to optionals happening in this statement. The equivalent case condition case let value as T = value doesn't use the ? symbol at all.

if let value as T { ... }
3 Likes

x on its own isn’t an optional, so I think there needs to be something alluding to wrapping something in an optional for the if let to then unwrap.

2 Likes

Agreed.

Also, for if let foo = foo and if let foo I think of it as just eliding / omitting the redundant = foo, rather than using a different concept or syntax entirely.

If we apply the same to if let foo = foo as? T, it gives us if let foo as? T. Keeping this model would seem preferable for consistency and predictability.

4 Likes

I understand the appeal, but I don't think reusing the name is a good idea. By casting, we make something more specific, which deserves a more specific name:

if let cat = animal as? Cat {
    // ....
} else if let dog = animal as? Dog {
    // ....
} else {
    // ....
}
6 Likes

There are two forms being conflated in this idea.

When you're not casting, but actually dealing with an Optional, the progression of sugar is clear:

let value: Optional = 0
if case .some(let value) = value { }
if case let value? = value { }
if let value = value { }
if let value { }

But otherwise, there are two forms to shorten, depending on if you're adding optionality or not:

let value: Any = 0

if case .some(let value) = value as? Int { }
if case let value? = value as? Int { }
if let value = value as? Int { }

if case let value as Int = value { }

The latter form is not what was addressed in Swift 5.7. So while only what's already been proposed is necessary for consistency—and readability— I propose that shortened case forms should also compile:

let value: Any = 0
if let value as? Int { }
if case let value as Int { }
let value: Optional = 0
if case let value? { }

This is all with the caveat that the existing spelling has always been broken.

We should have gotten the proposed if let value? (leading to if let value? as? Int for this thread) instead, but we didn't, because what should have been in the language from the start,

if let value = value?

is instead

if let value = value

:crying_cat_face:

2 Likes