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...? 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