I suggest you split this into 2 separate proposals. The second part seems much, 
much more controversial than the first.

Cheers,
Jaden Geller

> On Feb 28, 2017, at 11:01 AM, 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 { 
>     ... 
> }
> In-parenthesis binding avoids accidental shadowing. It eliminates this class 
> of error by adding let and var key words to each use point. This creates 
> longer call sites but enumerations rarely contain more than three or four 
> associated items.
> 
> Adopting point-of-use binding enhances clarity and readability. Both if case 
> let and if case var (plus case varand case let) may look like single compound 
> keywords rather than a combination of two distinct actions to developers 
> unfamiliar with this syntax.
> 
>  
> <https://gist.github.com/erica/06dad9bbe1a70290fe6b89a64f73bc0c#pattern-matching-with-conditional-binding>Pattern
>  Matching with Conditional Binding
> 
> Swift's guard case and if case align statement design with the switch 
> statement, moving the matched value to the right of an equal sign.
> 
> switch value {
>     case .enumeration(let embedded): ...
> }
> 
> if case .enumeration(let embedded) = value
> The status quo for the = operator is iteratively built up in this fashion:
> 
> = performs assignment
> let x = performs binding
> if let x = performs conditional binding on optionals
> if case .foo(let x) = performs conditional binding on enumerations and 
> applies pattern matching
> Using if case/guard case in the absense of conditional binding duplicates 
> basic pattern matching with less obvious meaning. These two statements are 
> functionally identical:
> 
> if range ~= myValue { ... } // simpler
> if case range = myValue { ... } // confusing
> Issues with the current design include:
> 
> guard case and if case look like standard non-conditional assignment 
> statements but they are not assignment statements. Using the assignment 
> operator violates the principle of least astonishment 
> <https://en.wikipedia.org/wiki/Principle_of_least_astonishment>.
> In switch, a case is followed by a colon, not an assignment operator.
> Swift has a pattern matching operator (~=) but does not use it here.
> case syntax is wordy. The statement includes case, =, and optionally let/var 
> conditional binding. Design alternatives could streamline this syntax, 
> enhance clarity, and introduce a more concise format.
>  
> <https://gist.github.com/erica/06dad9bbe1a70290fe6b89a64f73bc0c#detailed-design>Detailed
>  Design
> 
> This proposal adopts point-of-use conditional binding and recommends one of 
> the following designs. A successful design will replace the current syntax 
> with a simpler grammar that prioritizes pattern matching and support 
> conditional binding.
> 
>  
> <https://gist.github.com/erica/06dad9bbe1a70290fe6b89a64f73bc0c#design-1-using-the-pattern-matching-operator>Design
>  1: Using the Pattern Matching Operator
> 
> This design drops the case keyword and replaces = with ~=. The results look 
> like this, showcasing a variety of letplacement, variable binding, and 
> optional sugar alternatives.
> 
> guard .success(let value) ~= result else { ... }
> guard .success(var value) ~= result else { ... }
> if .success(let value) ~= result { ... }
> if .success(var value) ~= result { ... }
> guard let x? ~= anOptional else { ... }
> if let x? ~= anOptional { ... }
> In this design:
> 
> The case keyword is subsumed into the (existing) pattern matching operator
> The statements adopt the existing if-let/if var and guard-let/guard var 
> syntax, including Optionalsyntactic sugar.
> if let x = anOptional { ... } // current
> 
> if case let x? = anOptional { ... } // would be removed
> if let x? ~= anOptional { ... } // proposed replacement for `if case`
> Pattern matching without conditional binding simplifies to a standalone 
> Boolean condition clause. On adopting this syntax, the two identical range 
> tests naturally unify to this single version:
> 
> if range ~= myValue { ... } // before
> if case range = myValue { ... } // before
> 
> if range ~= myValue { ... } // after
>  
> <https://gist.github.com/erica/06dad9bbe1a70290fe6b89a64f73bc0c#design-2-using-a-declare-and-assign-operator>Design
>  2: Using a Declare and Assign Operator
> 
> This design introduces new := "declare and assign" operator. This operator 
> eliminates the need for explicit let, although the keyword is allowed and 
> most house style guides would recommend its use:
> 
> guard .success(value) := result else { ... } 
> guard .success(let value) := result else { ... }
> if .success(value) := result { ... }
> if .success(let value) := result { ... }
> guard value? := anOptional else { ... } // newly legal, although unnecessary
> guard let value? := anOptional else { ... } // newly legal, although 
> unnecessary
> Assignments to variables require the var keyword, enabling coders to clarify 
> the distinct roles in mix-and-match pattern matching:
> 
> guard .pair(value1, var value2) := result else { ... } // implied let
> guard .pair(let value1, var value2) := result else { ... } // explicit let
> if .success(var value) := result { ... } // variable assignment
> guard var x? := anOptional else { ... } // variable assignment
> guard var x := anOptional else { ... } // simpler variable assignment
> guard var x = anOptional else { ... } // even simpler (current) variable 
> assignment
> guard x := anOptional else { ... } // new constant assignment
> Adopting this syntax provides more natural results for binding associated 
> enumeration variables.
> 
>  
> <https://gist.github.com/erica/06dad9bbe1a70290fe6b89a64f73bc0c#excluded-from-this-proposal>Excluded
>  from this proposal
> 
> This proposal does not address switch case or for case beyond internal 
> binding requirements.
> 
>  
> <https://gist.github.com/erica/06dad9bbe1a70290fe6b89a64f73bc0c#impact-on-existing-code>Impact
>  on Existing Code
> 
> This proposal is breaking and would require migration. External let or var 
> would automatically be moved by fixits into use points. Current guard case 
> and if case syntax would be migrated to the new design.
> 
>  
> <https://gist.github.com/erica/06dad9bbe1a70290fe6b89a64f73bc0c#timeline>Timeline
> 
> Although removing if case and guard case are breaking, this proposal should 
> wait until Swift 4 Stage two to allow proper debate and consideration from 
> the core team.
> 
>  
> <https://gist.github.com/erica/06dad9bbe1a70290fe6b89a64f73bc0c#alternatives-considered>Alternatives
>  Considered
> 
> Leaving the grammar as-is, albeit confusing
> Retaining case and replacing the equal sign with ~= (pattern matching) or : 
> (to match the switch statement).
> Adding matches or is as an alternative to the pattern matching operator
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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

Reply via email to