[swift-evolution] guard let x = x

Charlie Monroe charlie at charliemonroe.net
Tue Nov 1 00:27:59 CDT 2016


> On Nov 1, 2016, at 2:46 AM, Xiaodi Wu via swift-evolution <swift-evolution at swift.org> wrote:
> 
> On Mon, Oct 31, 2016 at 8:37 PM, Joe Groff via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
> Sorry for piling onto the bikeshed. We do already have a notation for testing that an Optional isn't nil, `x != nil`. We could theoretically bless `<decl ref> != nil` as a statement condition to also unwrap the referenced declaration in the scope guarded by the condition. (`<decl ref> is T` could similarly rebind a declaration as the cast type.)
> 
> I think we'd have some weirdness. For instance:
> 
> ```
> guard x != nil || x == y else { break }
> // oops, now x isn't unwrapped anymore because I added a condition
> ```

This is what I suggested a few emails back, but perhaps failed to explain myself that well - my suggestion, however, used the "nonnil" keyword instead, which would prevent you from adding || condition:

guard nonnil x, x == y else { break }

To me this reads more naturally than guard unwrap x, x == y else { break }

> 
> Also, it'd be unexpected for it to be blessed for guard but not if:
> 
> ```
> if x != nil {
>   // is x unwrapped here?
>   // if so, this would be source-breaking...
>   // if not, it would be surprisingly inconsistent
> }
> ```
> 
> 
> 
> -Joe
> 
> > On Oct 28, 2016, at 3:34 PM, Erica Sadun via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
> >
> >
> >> On Oct 26, 2016, at 11:39 AM, Chris Lattner via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
> >>
> >>
> >>> On Oct 26, 2016, at 10:23 AM, Joshua Alvarado <alvaradojoshua0 at gmail.com <mailto:alvaradojoshua0 at gmail.com>> wrote:
> >>>
> >>> In your example the keyword only makes sense if you are shadowing the optional variable. How would unwrap work with a different name?
> >>
> >> It wouldn’t: “unwrap” would never include an equal sign.  If you want to do that, use a standard "if let”.
> >>
> >> -Chris
> >
> > So I can stop thinking about this. Gist is here: https://gist.github.com/erica/db9ce92b3d23cb20799460f603c0ae7c <https://gist.github.com/erica/db9ce92b3d23cb20799460f603c0ae7c>
> >
> > -- E
> >
> >
> > Introducing unwrap
> >
> >       • Proposal: TBD
> >       • Author: Erica Sadun, Chris Lattner, David Goodine
> >       • Status: TBD
> >       • Review manager: TBD
> > Introduction
> >
> > This proposal introduces unwrap, simplifying common shadowing and allowing a unified syntax for one-item associated values such as Result types.
> >
> > Swift-evolution thread: guard let x = x
> >
> > Motivation
> >
> > Swift lacks a unified, safe way to bind an optional or single-value enumeration to a shadowed varaiable that is guaranteed to be the same name. Introducing unwrap ensures the conditionally bound item does not accidentally shadow any other item.
> >
> > Compare:
> >
> > guard let foobar = foobar else { …
> >  }
> >
> > guard unwrap foobar else { … }
> > Using unwrap eliminates repetition ("foobar = foobar" fails DRY principles) and retains clarity. The keyword is common, simple to understand, and easy to search for if Swift users are unfamiliar with it.
> >
> > This syntax simplifies one-item associated value enumerations by offering a common syntax. Compare:
> >
> > enum Result<T> { case success(T), error(Error
> > ) }
> >
> >
> > guard case let .success(value) = result else { ...
> >  }
> >
> > guard unwrap result else { ... }
> > In the latter case result is bound to the wrapped value. Again, it is simpler and clearer, even with non-Optional types.
> >
> > Detailed Design
> >
> > unwrap can be used with any one-value enumeration. The unwrapped value is bound to the same symbol as the associated type.
> >
> > enum TypeName<T, U> { case anycase(T), anothercase(U) }
> >
> > // First and second are type `TypeName`
> > let first = TypeName.anyCase(value1)
> > let second = TypeName. anothercase(value2)
> >
> > guard unwrap first else { ... }
> > // first is now shadowed as type T
> >
> > guard unwrap second else { ... }
> > // second is now shadowed as type U
> >
> > Impact on Existing Code
> >
> > This change is additive and has no impact on existing code other than intentional refactoring.
> >
> > Timeline
> >
> > This proposal is additive and not suited for consideration until Swift 4 phase 2
> >
> > Alternatives Considered
> >
> >       • Using a bind keyword. Past discussions were held in the first week of February 2016.
> >       • Fixing pattern matching grammar
> >       • Not using this approach
> >
> > _______________________________________________
> > swift-evolution mailing list
> > swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> > https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20161101/21014cd6/attachment.html>


More information about the swift-evolution mailing list