I like the ~> operator, but not := operator. It makes the language inconsistent. Then we should allow using it without "if" just like this: mylet := "hey there"
I think we should keep let as it was and avoid := P.S.: it also looks too much Pascal-ish :) On Tue, 28 Feb 2017 at 21:02 Erica Sadun via swift-evolution < [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 > > 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 valuesenum Value<T> { case > one(T), two(T, T), three(T, T, T) } > // An example with two associated valueslet example2: Value<Character> = > .two("a", "b") > // A bound symbollet 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 { ... } // simplerif 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 { ... } // currentif case let x? = anOptional { ... } > // would be removedif 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 { ... } // beforeif case range = myValue { ... } // > beforeif 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 unnecessaryguard 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 letguard > .pair(let value1, var value2) := result else { ... } // explicit letif > .success(var value) := result { ... } // variable assignmentguard var x? := > anOptional else { ... } // variable assignmentguard var x := anOptional else > { ... } // simpler variable assignmentguard var x = anOptional else { ... } > // even simpler (current) variable assignmentguard 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 > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
