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