[swift-evolution] Proposal Sketch: simplify optional unwrapping syntax
Daniel Hooper
danielchasehooper at gmail.com
Fri Dec 11 11:17:46 CST 2015
I don't think we should discuss "with" here as that is a separate proposal.
I'm trying to draw attention of the approach of Swift generating shadow
variables for you when an optional has been proven to be non-null.
I didn't say we should remove if/guard let. They would stay.
My proposal is to improve readability and reduce verbosity by generating
shadow variables after "x != nil" checks. The "with x {}" and "if let x {}"
approaches only reduce verbosity, at the additional cost of adding new
keywords or syntax to the language, and do not really improve readability.
Due to this, generating a shadow variable after "x != nil" is the most
straightforward, lowest impact and readable approach.
ilya, you bring up a good point about "create shadow->write to
original->read shadow" situations being potentially confusing. However "if
let x = x" is very common in situations that this isn't an issue: taking a
quick look at my code, 50% of all "if/guard let x = x" are on local
variables that cannot possibly change out from under the shadow variable.
If that could lead to confusion in a given situation, you could fall back
on "if let x = maybe_x" to make it clearer that you're operating on a copy
of a variable that won't change out from under you. Alternatively, the "if
x != nil { x.bla() }" syntax could only be allowed on optionals in the
current function scope.
On Fri, Dec 11, 2015 at 11:41 AM Sean Heber <sean at fifthace.com> wrote:
> This has come up a few times. I’ve thrown my 2cents into a variant of
> “with” to solve this rather than messing with the meaning of if-let:
>
> For example:
>
> var x: MyType?
>
> with x {
> x.someFunction() // okay - this entire block is skipped if
> “x” is nil anyway
> }
> x.someFunction() // not okay as-is since x is optional
>
>
> Using the definition of “with” from Erica’s Method Cascading proposal
> https://gist.github.com/erica/6794d48d917e2084d6ed, you could even drop
> the variable reference itself from inside the block body:
>
> with x {
> someFunction() // would call “someFunction()” on “x”
> }
>
>
> And I’d additionally propose that if you wanted to replace if-let-else,
> you could potentially do this:
>
> if with x {
> // x is known non-nil
> } else {
> // x is known to be nil
> }
> // x is optional and nil-ness is unknown
>
>
> l8r
> Sean
>
>
> > On Dec 11, 2015, at 10:28 AM, Marc Knaup via swift-evolution <
> swift-evolution at swift.org> wrote:
> >
> > One problem with dropping if/guard let is something like this:
> >
> > if let x = a?.b.c?.d, y = something(x) {
> > …
> > }
> >
> > would then have to become this:
> >
> > let x = a?.b.c?.d
> > if x != nil {
> > let y = something(x)
> > if y != nil {
> > …
> > }
> > }
> >
> > I'm fine with
> > if let x
> > as a shortcut for
> > if let x = x
> >
> > It just reads a bit weird - like declaring an immutable variable with no
> type and no value.
> >
> >
> > On Fri, Dec 11, 2015 at 5:19 PM, Jeff Kelley via swift-evolution <
> swift-evolution at swift.org> wrote:
> > I’ve had similar ideas to this. Instead of ditching the if let syntax
> altogether, another approach would be to use the existing name if no new
> name is given, so that this code:
> >
> > if let foo = foo { /* use foo */ }
> >
> > could become this code:
> >
> > if let foo { /* use foo */ }
> >
> > In both cases, foo is non-optional inside the braces. If you gave it
> another name with the if let syntax, that would work as it does today.
> >
> >
> > Jeff Kelley
> >
> > SlaunchaMan at gmail.com | @SlaunchaMan | jeffkelley.org
> >
> >> On Dec 11, 2015, at 11:11 AM, Daniel Hooper via swift-evolution <
> swift-evolution at swift.org> wrote:
> >>
> >> A very common pattern in swift code is to "guard let" or "if let"
> optionals - this works by creating a new non-optional variable to be used
> by future code. Often, the new variable is given the same name as the
> original optional variable, creating a shadow variable. This approach leads
> to odd looking code like this:
> >>
> >> if let nearestX = nearestX { closest = nearestX }
> >> guard let layer = layer else { continue }
> >> // use layer
> >>
> >> At a glance, and to Swift newcomers, this code looks completely
> non-sensical. It's also verbose for simply ensuring the variable is non-nil.
> >>
> >> The solution:
> >> Swift should generate unwrapped shadow variables after nil checking.
> The compiler would treat the below code as if it had created an unwrapped
> shadow variable.
> >>
> >> if nearestX != nil { closest = nearestX } // notice that nearestX isn't
> force unwrapped
> >> guard layer != nil else { continue }
> >> // use layer, without force unwrapping
> >>
> >> Why force unwrapping isn't a good alternative:
> >> You might suggest force unwrapping variables when they're inside an if
> or after a guard that checks for nil. While this does allow for the "layer
> = nil" syntax, it results in code that is less resilient to change. Imagine
> that this code was written:
> >>
> >> {code:java}
> >> if layer != nil {
> >> // lots of code before //
> >> layer!.backgroundColor = newColor
> >> // lots of code after //
> >> }
> >> {code}
> >>
> >> And much later, you need to use some of the the code in the if body
> elsewhere, so you copy and paste a huge chunk of it. You likely won't
> notice the force unwrap, and unless you're lucky, you probably didn't paste
> it into an if that checked layer for nil. So you get a crash. Because of
> this, it's important we make safe optional unwrapping as easy and sensical
> as possible, and minimize the situations that you would need to force
> unwrap.
> >> _______________________________________________
> >> swift-evolution mailing list
> >> swift-evolution at swift.org
> >> https://lists.swift.org/mailman/listinfo/swift-evolution
> >
> >
> >
> > _______________________________________________
> > swift-evolution mailing list
> > swift-evolution at swift.org
> > https://lists.swift.org/mailman/listinfo/swift-evolution
> >
> >
> > _______________________________________________
> > swift-evolution mailing list
> > swift-evolution at swift.org
> > https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151211/ece1772a/attachment.html>
More information about the swift-evolution
mailing list