Aha! I found a proposal Erica put forth about this a year and a while ago—
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160704/023955.html <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160704/023955.html> > On Nov 18, 2017, at 11:30 AM, Peter Kamb <[email protected]> wrote: > > > alternative to `fallthrough` that would continue matching cases > > Yes, that would be interesting to look into. Do you have any references or > remember what the proposed keyword was called? Do any other languages have > this feature? > > > > On Sat, Nov 18, 2017 at 10:53 AM Kevin Nattinger <[email protected] > <mailto:[email protected]>> 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 > > <[email protected] <mailto:[email protected]>> 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 > > [email protected] <mailto:[email protected]> > > https://lists.swift.org/mailman/listinfo/swift-evolution > > <https://lists.swift.org/mailman/listinfo/swift-evolution> >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
