I guess I should also include the example where the user actually wanted the
oldValue to be "x":
if case let .two(newValue, value) = example, value == oldValue { ... }
No surprises there, even if another conditional is required.
— Pyry
> On 1 Mar 2017, at 22.53, Pyry Jahkola via swift-evolution
> <[email protected]> wrote:
>
> 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
>> <[email protected] <mailto:[email protected]>> 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
> [email protected] <mailto:[email protected]>
> https://lists.swift.org/mailman/listinfo/swift-evolution
> <https://lists.swift.org/mailman/listinfo/swift-evolution>
--
Pyry Jahkola
[email protected]
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution