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