<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div></div><div><br></div><div><br>Le 18 nov. 2017 à 23:47, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com">xiaodi.wu@gmail.com</a>&gt; a écrit&nbsp;:<br><br></div><blockquote type="cite"><div><div>On Sat, Nov 18, 2017 at 16:25 Benjamin G &lt;<a href="mailto:benjamin.garrigues@gmail.com">benjamin.garrigues@gmail.com</a>&gt; wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>I think because it's not immediately obvious with multiple if statement, that they all try to compare the same expression to different patterns.<div><br></div><div>match exp {</div><div>case 1</div><div>case 2</div><div>}</div><div>vs</div><div>if case 1 = exp</div><div>if case 2 = anotherexp&nbsp;</div></div></blockquote><div dir="auto"><br></div><div dir="auto">And this is a problem that requires a new syntax because...?</div></div></div></div></blockquote><div><br></div><div>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).</div><div><br></div><div>Actually i think there's a nice symetry betwen enum &amp; switch on one side and optionset &amp; match on the other hand. It's interesting but i don't know if it's useful in practice TBH.</div><div><br></div><br><blockquote type="cite"><div><div><div class="gmail_quote"><div dir="auto"><br></div><div dir="auto">Consider that “exp” can be mutated in case 1; now reflect whether the proposed syntax facilitates or hinders correct code.</div><div dir="auto"><br></div><div dir="auto"><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div></div></div><div class="gmail_extra"><div class="gmail_quote">On Sat, Nov 18, 2017 at 10:43 PM, Xiaodi Wu via swift-evolution <span>&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><span>On Sat, Nov 18, 2017 at 3:12 PM, Peter Kamb <span>&lt;<a href="mailto:peterkamb@gmail.com" target="_blank">peterkamb@gmail.com</a>&gt;</span> wrote:<br></span><div class="gmail_extra"><div class="gmail_quote"><span><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>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.<div><br></div><div>But AFAIK there's currently no ability in Swift to:</div><div><br></div><div>"Evaluate a *single* control expression against all of these patterns, and execute any and all cases that match"<div><div><br></div><div>Multiple `if-case` statements, each re-stating the control expression, are ok.</div><div><br></div><div>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.</div></div></div></div></blockquote><div><br></div></span><div>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"?</div><div><div class="m_-1042011099583709088h5"><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="m_-1042011099583709088m_1215296999888247609HOEnZb"><div class="m_-1042011099583709088m_1215296999888247609h5"><div class="gmail_extra"><div class="gmail_quote">On Sat, Nov 18, 2017 at 11:18 AM, Xiaodi Wu <span>&lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank">xiaodi.wu@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>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.<div><div class="m_-1042011099583709088m_1215296999888247609m_8769700845806481439h5"><div><br><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Nov 18, 2017 at 12:53 PM, Kevin Nattinger via swift-evolution <span>&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">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?<br>
<div class="m_-1042011099583709088m_1215296999888247609m_8769700845806481439m_-9186521494073167498HOEnZb"><div class="m_-1042011099583709088m_1215296999888247609m_8769700845806481439m_-9186521494073167498h5"><br>
&gt; On Nov 17, 2017, at 12:06 PM, Peter Kamb via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:<br>
&gt;<br>
&gt; ## Title<br>
&gt;<br>
&gt; Add `match` statement as `switch`-like syntax alternative to `if case` pattern matching<br>
&gt;<br>
&gt; ## Summary:<br>
&gt;<br>
&gt; 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`.<br>
&gt;<br>
&gt; However, the `switch` statement has several unique behaviors unrelated to pattern matching. Namely:<br>
&gt;<br>
&gt;&nbsp; - Only the *first* matching case is executed. Subsequent matching cases are not executed.<br>
&gt;&nbsp; - `default:` case is required, even for expressions where a default case does not make sense.<br>
&gt;<br>
&gt; These behaviors prevent `switch` from being used as a generic match-patterns-against-a-single-expression statement.<br>
&gt;<br>
&gt; Swift should contain an equally-good pattern-matching statement that does not limit itself single-branch switching.<br>
&gt;<br>
&gt; ## Pitch:<br>
&gt;<br>
&gt; Add a `match` statement with the same elegant syntax as the `switch` statement, but without any of the "branch switching" baggage.<br>
&gt;<br>
&gt; ```<br>
&gt; match someValue {<br>
&gt; case patternOne:<br>
&gt;&nbsp; &nbsp; &nbsp;always executed if pattern matches<br>
&gt; case patternTwo:<br>
&gt;&nbsp; &nbsp; &nbsp;always executed if pattern matches<br>
&gt; }<br>
&gt; ```<br>
&gt;<br>
&gt; The match statement would allow a single value to be filtered through *multiple* cases of pattern-matching evaluation.<br>
&gt;<br>
&gt; ## Example:<br>
&gt;<br>
&gt; ```<br>
&gt; struct TextFlags: OptionSet {<br>
&gt;&nbsp; &nbsp; &nbsp;let rawValue: Int<br>
&gt;&nbsp; &nbsp; &nbsp;static let italics = TextFlags(rawValue: 1 &lt;&lt; 1)<br>
&gt;&nbsp; &nbsp; &nbsp;static let bold&nbsp; &nbsp; = TextFlags(rawValue: 1 &lt;&lt; 2)<br>
&gt; }<br>
&gt;<br>
&gt; let textFlags: TextFlags = [.italics, .bold]<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; // SWITCH STATEMENT<br>
&gt; switch textFlags {<br>
&gt; case let x where x.contains(.italics):<br>
&gt;&nbsp; &nbsp; &nbsp;print("italics")<br>
&gt; case let x where x.contains(.bold):<br>
&gt;&nbsp; &nbsp; &nbsp;print("bold")<br>
&gt; default:<br>
&gt;&nbsp; &nbsp; &nbsp;print("forced to include a default case")<br>
&gt; }<br>
&gt; // prints "italics"<br>
&gt; // Does NOT print "bold", despite .bold being set.<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; // MATCH STATEMENT<br>
&gt; match textFlags {<br>
&gt; case let x where x.contains(.italics):<br>
&gt;&nbsp; &nbsp; &nbsp;print("italics")<br>
&gt; case let x where x.contains(.bold):<br>
&gt;&nbsp; &nbsp; &nbsp;print("bold")<br>
&gt; }<br>
&gt; // prints "italics"<br>
&gt; // prints "bold"<br>
&gt; ```<br>
&gt;<br>
&gt; ## Enum vs. OptionSet<br>
&gt;<br>
&gt; The basic difference between `switch` and `match` is the same conceptual difference between `Emum` and an `OptionSet` bitmask.<br>
&gt;<br>
&gt; `switch` is essentially designed for enums: switching to a single logical branch based on the single distinct case represented by the enum.<br>
&gt;<br>
&gt; `match` would be designed for OptionSet bitmasks and similar constructs. Executing behavior for *any and all* of the following cases and patterns that match.<br>
&gt;<br>
&gt; 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.<br>
&gt;<br>
&gt; ## Existing Alternatives<br>
&gt;<br>
&gt; `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.<br>
&gt;<br>
&gt; Example using a string of independent `if case` statements:<br>
&gt;<br>
&gt; ```<br>
&gt; if case let x = textFlags, x.contains(.italics) {<br>
&gt;&nbsp; &nbsp; &nbsp;print("italics")<br>
&gt; }<br>
&gt;<br>
&gt; if case let x = textFlags, x.contains(.bold) {<br>
&gt;&nbsp; &nbsp; &nbsp;print("bold")<br>
&gt; }<br>
&gt; ```<br>
&gt;<br>
&gt; ## `match` statement benefits:<br>
&gt;<br>
&gt;&nbsp; - Allow filtering a single object through *multiple* cases of pattern matching, executing *all* cases that match.<br>
&gt;<br>
&gt;&nbsp; - A syntax that exactly aligns with the familiar, succinct, elegant, and understandable `switch` syntax.<br>
&gt;<br>
&gt; - The keyword "match" highlights that pattern matching will occur. Would be even better than `switch` for initial introductions to pattern-matching.<br>
&gt;<br>
&gt;&nbsp; - 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) {`<br>
&gt;<br>
&gt;&nbsp; - 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."<br>
&gt;<br>
&gt;&nbsp; - A single `match controlExpression` at the top rather than `controlExpression` being repeated (and possibly changed) in every single `if case` statement.<br>
&gt;<br>
&gt;&nbsp; - 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.<br>
&gt;<br>
&gt;&nbsp; - 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.<br>
&gt;<br>
&gt; ```<br>
&gt;&nbsp; match value { case pattern:<br>
&gt;&nbsp; &nbsp; &nbsp;print("matched")<br>
&gt; }<br>
&gt; ```<br>
&gt;<br>
&gt;&nbsp; - 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.)<br>
&gt;<br>
&gt; ## Prototype<br>
&gt;<br>
&gt; 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:<br>
&gt;<br>
&gt; ```<br>
&gt; match: for eachCase in 0...1 {<br>
&gt; switch (eachCase, textFlags) {<br>
&gt; case (0, let x) where x.contains(.italics):<br>
&gt;&nbsp; &nbsp; &nbsp;print("italics")<br>
&gt; case (1, let x) where x.contains(.bold):<br>
&gt;&nbsp; &nbsp; &nbsp;print("bold")<br>
&gt; default: break }<br>
&gt; }<br>
&gt;<br>
&gt; // prints "italics"<br>
&gt; // prints "bold"<br>
&gt; ```<br>
&gt;<br>
&gt; ## Notes / Discussion:<br>
&gt;<br>
&gt; - 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!<br>
&gt;<br>
&gt; - 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.<br>
&gt;<br>
&gt; - FizzBuzz using proposed Swift `match` statement:<br>
&gt;<br>
&gt; ```<br>
&gt; for i in 1...100 {<br>
&gt;&nbsp; &nbsp; &nbsp;var output = ""<br>
&gt;&nbsp; &nbsp; &nbsp;match 0 {<br>
&gt;&nbsp; &nbsp; &nbsp;case (i % 3): output += "Fizz"<br>
&gt;&nbsp; &nbsp; &nbsp;case (i % 3): output += "Buzz"<br>
&gt;&nbsp; &nbsp; &nbsp;default:&nbsp; &nbsp; &nbsp; output = String(i)<br>
&gt;&nbsp; &nbsp; &nbsp;}<br>
&gt;<br>
&gt;&nbsp; &nbsp; &nbsp;print(output)<br>
&gt; }<br>
&gt;<br>
&gt; // `15` prints "FizzBuzz"<br>
&gt; ```<br>
</div></div><div class="m_-1042011099583709088m_1215296999888247609m_8769700845806481439m_-9186521494073167498HOEnZb"><div class="m_-1042011099583709088m_1215296999888247609m_8769700845806481439m_-9186521494073167498h5">&gt; _______________________________________________<br>
&gt; swift-evolution mailing list<br>
&gt; <a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
&gt; <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
<br>
_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
</div></div></blockquote></div><br></div></div></div></div></div>
</blockquote></div><br></div>
</div></div></blockquote></div></div></div><br></div></div>
<br>_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
<br></blockquote></div><br></div>
</blockquote></div></div>
</div></blockquote></body></html>