Erica,

Instead of going into all these lengths introducing new syntax, why not simply 
turn it into a warning when a `case let` binding shadows an existing variable 
with the exact same type (which supposedly also conforms to Equatable)?

Examples, including how to silence the said warning:

    enum Value<T> { case one(T), two(T, T), three(T, T, T) }
    
    let example: Value<String> = .two("a", "b")
    let oldValue = "x"
    // (Besides, you probably intended `oldValue` to be a `Character` in your
    // example. Well, it's a `String` in mine.)
    
    if case let .two(newValue, oldValue) = example { ... }
    //                         ~~~~~~~~
    // warning: 'oldValue' shadows an existing variable of same type 'String'
    
    if case let .two(newValue, (oldValue)) = example { assert(oldValue == "b") }
    // Ok, adding extra parentheses silences the warning.

    if case let .one(example) = example { ... }
    // Ok, because there's no way the author would equate the `example: String`
    // in the LHS to the `example: Value<String>` of the RHS.
    
    let maybe: Optional = "perhaps"
    if case let maybe? = maybe { ... }
    if case let .some(maybe) = maybe { ... }
    // Again, none of these examples would be affected by the warning, because
    // the `maybe: String` bound in the `case let` has a different type than
    // the `maybe: String?` in the outer scope.

Personally, I do like the convenience that I can bind several variables with 
one `let` keyword in a case expression. And I can't see the appeal to making 
`~=`, let alone a completely new special-syntax assignment operator, more 
prominent in Swift.

— Pyry

> On 28 Feb 2017, at 21.01, Erica Sadun via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
> The following draft proposal addresses one matter of substance (eliminating 
> edge case errors by adopting at-site conditional binding) and one of style 
> (using the pattern match operator consistently). Its discussion was deferred 
> from Phase 1 and remains in a fairly early stage. Your feedback will help me 
> decide whether this is a proposal I want to keep developing or one that I 
> should set aside and focus on other matters. Thank you. -- E
> 
> The work-in-progress gist is here:  
> https://gist.github.com/erica/06dad9bbe1a70290fe6b89a64f73bc0c 
> <https://gist.github.com/erica/06dad9bbe1a70290fe6b89a64f73bc0c> 
> 
> Simplifying case syntax
> 
> Proposal: TBD
> Author: Erica Sadun <https://github.com/erica>
> Status: TBD
> Review manager: TBD
>  
> <https://gist.github.com/erica/06dad9bbe1a70290fe6b89a64f73bc0c#introduction>Introduction
> 
> This proposal re-architects case syntax grammar to reduce potential errors 
> and simplify unwrapping enumerations. 
> 
> Swift-evolution thread: [Pitch] Reimagining guard case/if case 
> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20161024/tbd.html>
>  
> <https://gist.github.com/erica/06dad9bbe1a70290fe6b89a64f73bc0c#motivation>Motivation
> 
> In its current design, Swift case binding suffers from two weaknesses.
> 
> Mixed external and internal let/var binding may introduce errors from 
> uncommon edge cases.
> Real-world users may not consider the parallel construction between if 
> case/guard case with switchstatements or naturally connect the two layouts.
>  
> <https://gist.github.com/erica/06dad9bbe1a70290fe6b89a64f73bc0c#internal-case-binding>Internal
>  Case Binding
> 
> When pattern matching, it's common to bind a variable or constant. It's 
> uncommon but legal to use a bound value as an argument. Adopting an "always 
> explicit, always within the parentheses" rule adds consistency and safety to 
> Swift. 
> 
> Consider the following enumeration and values:
> 
> // An enum with one, two, or three associated values
> enum Value<T> { case one(T), two(T, T), three(T, T, T) }
> 
> // An example with two associated values
> let example2: Value<Character> = .two("a", "b")
> 
> // A bound symbol
> let oldValue = "x"
> This code's goal is to conditionally bind newValue and pattern match the 
> value stored in the oldValue symbol. The first example succeeds. The second 
> example compiles and runs but does not match the coder's intent. Using an 
> external letcreates a new oldValue shadow instead of pattern matching 
> oldValue's stored value.
> 
> // Safe
> if case .two(let newValue, oldValue) = example2 { 
>     ... 
> }
> 
> // Syntactically legal but incorrect
> if case let .two(newValue, oldValue) = example2 { 
>     ... 
> }
(…)

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to