> Le 18 nov. 2017 à 23:47, Xiaodi Wu <xiaodi...@gmail.com> a écrit : > >> On Sat, Nov 18, 2017 at 16:25 Benjamin G <benjamin.garrig...@gmail.com> >> wrote: >> I think because it's not immediately obvious with multiple if statement, >> that they all try to compare the same expression to different patterns. >> >> match exp { >> case 1 >> case 2 >> } >> vs >> if case 1 = exp >> if case 2 = anotherexp > > And this is a problem that requires a new syntax because...?
i don't think the reason is that different from creating "switch" : you can very well use "ifs" instead, it's just more convenient . It may provide exhaustive check in the case of optionset one day. But we can live without it ( much like we lived without switch before). Actually i think there's a nice symetry betwen enum & switch on one side and optionset & match on the other hand. It's interesting but i don't know if it's useful in practice TBH. > > Consider that “exp” can be mutated in case 1; now reflect whether the > proposed syntax facilitates or hinders correct code. > > >>> On Sat, Nov 18, 2017 at 10:43 PM, Xiaodi Wu via swift-evolution >>> <swift-evolution@swift.org> wrote: >>>> On Sat, Nov 18, 2017 at 3:12 PM, Peter Kamb <peterk...@gmail.com> wrote: >>> >>>> A high bar for new syntax is fair and expected, and by posting I was >>>> hoping to maybe find an alternative in the comments here. >>>> >>>> But AFAIK there's currently no ability in Swift to: >>>> >>>> "Evaluate a *single* control expression against all of these patterns, and >>>> execute any and all cases that match" >>>> >>>> Multiple `if-case` statements, each re-stating the control expression, are >>>> ok. >>>> >>>> But that's definitely not as clear or concise as a switch-like construct >>>> with the single control expression at the top. Or perhaps some other >>>> alternative such as the mentioned `continue` or somehow enumerating a set >>>> of cases. >>> >>> You're simply restating your proposed new syntax as the thing that's >>> missing. But what is the use case that motivates this construct? In what >>> way are multiple if-case statements "not as clear"? >>> >>>>> On Sat, Nov 18, 2017 at 11:18 AM, Xiaodi Wu <xiaodi...@gmail.com> wrote: >>>>> Robert is quite right--I'm not sure what we're designing for here. >>>>> There's a very high bar for introducing new syntax and a distaste for the >>>>> existing syntax is not a motivating use case. >>>>> >>>>> >>>>>> On Sat, Nov 18, 2017 at 12:53 PM, Kevin Nattinger via swift-evolution >>>>>> <swift-evolution@swift.org> wrote: >>>>>> There have been earlier suggestions for an alternative to `fallthrough` >>>>>> that would continue matching cases; I think that is much more likely to >>>>>> get support than a whole new construct with only a subtle difference >>>>>> from an existing one—would that be an acceptable alternative to you? >>>>>> >>>>>> > On Nov 17, 2017, at 12:06 PM, Peter Kamb via swift-evolution >>>>>> > <swift-evolution@swift.org> wrote: >>>>>> > >>>>>> > ## Title >>>>>> > >>>>>> > Add `match` statement as `switch`-like syntax alternative to `if case` >>>>>> > pattern matching >>>>>> > >>>>>> > ## Summary: >>>>>> > >>>>>> > The syntax of the `switch` statement is familiar, succinct, elegant, >>>>>> > and understandable. Swift pattern-matching tutorials use `switch` >>>>>> > statements almost exclusively, with small sections at the end for >>>>>> > alternatives such as `if case`. >>>>>> > >>>>>> > However, the `switch` statement has several unique behaviors unrelated >>>>>> > to pattern matching. Namely: >>>>>> > >>>>>> > - Only the *first* matching case is executed. Subsequent matching >>>>>> > cases are not executed. >>>>>> > - `default:` case is required, even for expressions where a default >>>>>> > case does not make sense. >>>>>> > >>>>>> > These behaviors prevent `switch` from being used as a generic >>>>>> > match-patterns-against-a-single-expression statement. >>>>>> > >>>>>> > Swift should contain an equally-good pattern-matching statement that >>>>>> > does not limit itself single-branch switching. >>>>>> > >>>>>> > ## Pitch: >>>>>> > >>>>>> > Add a `match` statement with the same elegant syntax as the `switch` >>>>>> > statement, but without any of the "branch switching" baggage. >>>>>> > >>>>>> > ``` >>>>>> > match someValue { >>>>>> > case patternOne: >>>>>> > always executed if pattern matches >>>>>> > case patternTwo: >>>>>> > always executed if pattern matches >>>>>> > } >>>>>> > ``` >>>>>> > >>>>>> > The match statement would allow a single value to be filtered through >>>>>> > *multiple* cases of pattern-matching evaluation. >>>>>> > >>>>>> > ## Example: >>>>>> > >>>>>> > ``` >>>>>> > struct TextFlags: OptionSet { >>>>>> > let rawValue: Int >>>>>> > static let italics = TextFlags(rawValue: 1 << 1) >>>>>> > static let bold = TextFlags(rawValue: 1 << 2) >>>>>> > } >>>>>> > >>>>>> > let textFlags: TextFlags = [.italics, .bold] >>>>>> > >>>>>> > >>>>>> > >>>>>> > // SWITCH STATEMENT >>>>>> > switch textFlags { >>>>>> > case let x where x.contains(.italics): >>>>>> > print("italics") >>>>>> > case let x where x.contains(.bold): >>>>>> > print("bold") >>>>>> > default: >>>>>> > print("forced to include a default case") >>>>>> > } >>>>>> > // prints "italics" >>>>>> > // Does NOT print "bold", despite .bold being set. >>>>>> > >>>>>> > >>>>>> > >>>>>> > // MATCH STATEMENT >>>>>> > match textFlags { >>>>>> > case let x where x.contains(.italics): >>>>>> > print("italics") >>>>>> > case let x where x.contains(.bold): >>>>>> > print("bold") >>>>>> > } >>>>>> > // prints "italics" >>>>>> > // prints "bold" >>>>>> > ``` >>>>>> > >>>>>> > ## Enum vs. OptionSet >>>>>> > >>>>>> > The basic difference between `switch` and `match` is the same >>>>>> > conceptual difference between `Emum` and an `OptionSet` bitmask. >>>>>> > >>>>>> > `switch` is essentially designed for enums: switching to a single >>>>>> > logical branch based on the single distinct case represented by the >>>>>> > enum. >>>>>> > >>>>>> > `match` would be designed for OptionSet bitmasks and similar >>>>>> > constructs. Executing behavior for *any and all* of the following >>>>>> > cases and patterns that match. >>>>>> > >>>>>> > The programmer would choose between `switch` or `match` based on the >>>>>> > goal of the pattern matching. For example, pattern matching a String. >>>>>> > `switch` would be appropriate for evaluating a String that represents >>>>>> > the rawValue of an enum. But `match` would be more appropriate for >>>>>> > evaluating a single input String against multiple >>>>>> > unrelated-to-each-other regexes. >>>>>> > >>>>>> > ## Existing Alternatives >>>>>> > >>>>>> > `switch` cannot be used to match multiple cases. There are several >>>>>> > ways "test a value against multiple patterns, executing behavior for >>>>>> > each pattern that matches", but none are as elegant and understandable >>>>>> > as the switch statement syntax. >>>>>> > >>>>>> > Example using a string of independent `if case` statements: >>>>>> > >>>>>> > ``` >>>>>> > if case let x = textFlags, x.contains(.italics) { >>>>>> > print("italics") >>>>>> > } >>>>>> > >>>>>> > if case let x = textFlags, x.contains(.bold) { >>>>>> > print("bold") >>>>>> > } >>>>>> > ``` >>>>>> > >>>>>> > ## `match` statement benefits: >>>>>> > >>>>>> > - Allow filtering a single object through *multiple* cases of pattern >>>>>> > matching, executing *all* cases that match. >>>>>> > >>>>>> > - A syntax that exactly aligns with the familiar, succinct, elegant, >>>>>> > and understandable `switch` syntax. >>>>>> > >>>>>> > - The keyword "match" highlights that pattern matching will occur. >>>>>> > Would be even better than `switch` for initial introductions to >>>>>> > pattern-matching. >>>>>> > >>>>>> > - No need to convert between the strangely slightly different syntax >>>>>> > of `switch` vs. `if case`, such as `case let x where >>>>>> > x.contains(.italics):` to `if case let x = textFlags, >>>>>> > x.contains(.italics) {` >>>>>> > >>>>>> > - Bring the "Expression Pattern" to non-branch-switching contexts. >>>>>> > Currently: "An expression pattern represents the value of an >>>>>> > expression. Expression patterns appear only in switch statement case >>>>>> > labels." >>>>>> > >>>>>> > - A single `match controlExpression` at the top rather than >>>>>> > `controlExpression` being repeated (and possibly changed) in every >>>>>> > single `if case` statement. >>>>>> > >>>>>> > - Duplicated `controlExpression` is an opportunity for bugs such as >>>>>> > typos or changes to the expression being evaluated in a *single* `if >>>>>> > case` from the set, rather than all cases. >>>>>> > >>>>>> > - Reduces to a pretty elegant single-case. This one-liner is an easy >>>>>> > "just delete whitespace" conversion from standard multi-line >>>>>> > switch/match syntax, whereas `if case` is not. >>>>>> > >>>>>> > ``` >>>>>> > match value { case pattern: >>>>>> > print("matched") >>>>>> > } >>>>>> > ``` >>>>>> > >>>>>> > - Eliminate the boilerplate `default: break` case line for >>>>>> > non-exhaustible expressions. Pretty much any non-Enum type being >>>>>> > evaluated is non-exhaustible. (This is not the *main* goal of this >>>>>> > proposal.) >>>>>> > >>>>>> > ## Prototype >>>>>> > >>>>>> > A prototype `match` statement can be created in Swift by wrapping a >>>>>> > `switch` statement in a loop and constructing each case to match only >>>>>> > on a given iteration of the loop: >>>>>> > >>>>>> > ``` >>>>>> > match: for eachCase in 0...1 { >>>>>> > switch (eachCase, textFlags) { >>>>>> > case (0, let x) where x.contains(.italics): >>>>>> > print("italics") >>>>>> > case (1, let x) where x.contains(.bold): >>>>>> > print("bold") >>>>>> > default: break } >>>>>> > } >>>>>> > >>>>>> > // prints "italics" >>>>>> > // prints "bold" >>>>>> > ``` >>>>>> > >>>>>> > ## Notes / Discussion: >>>>>> > >>>>>> > - Other Languages - I've been unable to find a switch-syntax >>>>>> > non-"switching" pattern-match operator in any other language. If you >>>>>> > know of any, please post! >>>>>> > >>>>>> > - Should `match` allow a `default:` case? It would be easy enough to >>>>>> > add one that functioned like switch's default case: run if *no other* >>>>>> > cases were executed. But, conceptually, should a "match any of these >>>>>> > patterns" statement have an else/default clause? I think it should, >>>>>> > unless there are any strong opinions. >>>>>> > >>>>>> > - FizzBuzz using proposed Swift `match` statement: >>>>>> > >>>>>> > ``` >>>>>> > for i in 1...100 { >>>>>> > var output = "" >>>>>> > match 0 { >>>>>> > case (i % 3): output += "Fizz" >>>>>> > case (i % 3): output += "Buzz" >>>>>> > default: output = String(i) >>>>>> > } >>>>>> > >>>>>> > print(output) >>>>>> > } >>>>>> > >>>>>> > // `15` prints "FizzBuzz" >>>>>> > ``` >>>>>> > _______________________________________________ >>>>>> > 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 >>>>> >>>> >>> >>> >>> _______________________________________________ >>> 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