<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Apr 2, 2017, at 5:12 PM, Xiaodi Wu <<a href="mailto:xiaodi.wu@gmail.com" class="">xiaodi.wu@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">On Sun, Apr 2, 2017 at 6:30 PM, Daniel Duan <span dir="ltr" class=""><<a href="mailto:daniel@duan.org" target="_blank" class="">daniel@duan.org</a>></span> wrote:<br class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""><br class=""></div><div class=""><snip> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="auto" class=""><div class=""><div class="gmail-h5"><blockquote type="cite" class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word" class=""><div class="">The key distinction we need to decide here is whether case labels are “cosmetic”. We don’t allow declaration of separate parameter name and internal name for associated values. I interpret that as we are enforcing the syntax sugar in function declaration where user can use one symbol to represent both:<br class=""></div><div class=""><br class=""></div><div class="">func f(x: Int) // is the same as func f(x x: Int)</div><div class=""><br class=""></div><div class="">It’s tempting to treat matching an enum value against a pattern as assigning a function value to a variable.</div></div></blockquote><div class=""><br class=""></div><div class="">Sorry, I am not sure I understand this sentence.</div></div></div></div></blockquote><div class=""><br class=""></div></div></div><div class="">Aka viewing the case pattern as simply an compound variable assignment as envisioned in the SE-0111 commentary. This way of the labels would be "cosmetic".</div></div></blockquote><div class=""><br class=""></div><div class="">I'm sorry. Still don't understand :(</div><div class=""><br class=""></div><div class="">I have a very simple understanding of what makes something "cosmetic." Simply, it's something that the API author can write, which the API consumer can choose to read but is never (or, at least, rarely) required to write.</div><div class=""> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="auto" class=""><span class="gmail-"><blockquote type="cite" class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><div class="">If that’s what we are doing, it makes perfect sense to say we get “ultimate glory” here with patterns. Meaning, as you suggested, we consider the case labels “cosmetic”. It’s really just tho parameter name in a function (the first of the two “x” in code comment above.</div><div class=""><br class=""></div><div class="">But that’s kind of a stretch isn’t it? An enum value is very different compared to a function value. Yes, there happen to be a function that constructs this enum value that’s declared when user declare a case, that function gets as much resemblance as any other. But the enum value it self deserves more consideration. Telling the user “do these things that you do with a function value” just makes pattern matching harder to explain, because we are *not* assigning nor invoking function values.</div></div></div></blockquote><div class=""><br class=""></div><div class="">Ah, I see. You think of the associated value as something distinct from the declaration used to initialize it. However, there is no spelling for an associated value other than what is used to initialize it. Given `case foo(bar: Int, baz: Int, boo: Int)`, previously, the full name of the case was `foo` and the associated value was `(bar: Int, baz: Int, boo: Int)`. Your proposal causes the full name of the case instead to be `foo(bar:baz:boo:)` and the associated value to be `(Int, Int, Int)`. Is that not your understanding of it?</div></div></div></div></blockquote><div class=""><br class=""></div></span>Yes<span class="gmail-"><br class=""><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class="">Pattern matching is just a matter of (a) indicating what case you want to identify with the pattern; and (b) what parts of the associated value you wish to match or to bind to variables. Part (a) is done by writing the name, either the base name or in full (i.e. either `foo` or `foo(bar:baz:boo:)`). Part (b) is done by writing `let myVariableName` in the intended positions.</div></div></div></div></div></blockquote><div class=""><br class=""></div></span>What I left out is that the internal/parameter names of a function are non-optional part of its signature (one must use exact parameter names to implement a method in a protocol, for example).</div></blockquote><div class=""><br class=""></div><div class="">That's not true, and if we change Swift's rules to make it true, my own code would become pervasively broken, and I suspect many others' code too.</div><div class=""><br class=""></div></div></div></div></div></blockquote><div>My apologies, not sure where I got that impression. </div><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class="">```</div><div class=""><div class="">protocol P {</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>func foo(_ bar: Int, _ baz: Int)</div><div class="">}</div><div class=""><br class=""></div><div class="">extension P {</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>func foo(_ a: Int, _ b: Int) {</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>print("Hello from P!")</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>}</div><div class="">}</div><div class=""><br class=""></div><div class="">struct S : P {</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>func foo(_ x: Int, _ y: Int) {</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>print("Hello world!")</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>}</div><div class="">}</div><div class=""><br class=""></div><div class="">struct T : P { }</div><div class=""><br class=""></div><div class="">let p: P = S()</div><div class="">p.foo(42, 42) // "Hello world!"</div><div class="">let q: P = T()</div><div class="">q.foo(42, 42) // "Hello from P!"</div></div><div class="">```</div><div class=""><br class=""></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="auto" class="">I prefer treating labels in case pattern matching the same way we treat parameter names in protocol method implementation (due to the symmetry between constructing/deconstructing body mentioned in my previous comments).</div></blockquote><div class=""><br class=""></div><div class="">Independent of the how internal names of a function are handled, I would strongly disagree with this idea as well. Implementing a protocol is the act of an API author--i.e., you are opting a type into a contract about its API. Pattern matching is the act of an API user. Swift has always observed a sharp differentiation between these two activities; it is, in essence, the dividing line between internal and not internal. We absolutely should not design pattern matching to parallel rules for API contracts.</div><div class=""><br class=""></div></div></div></div></div></blockquote>I’m not satisfied by your definition of API author/user. When I conform my type to, say, Equitable, or UITableViewDataSource, I consider myself *user* of an API in the form of a contract: to use functionality provided by this code, implement some stuff that meets some requirements associated with it. The author of these protocols specify these interfaces including what method name the user should conform with, what’s the best semantic for them, etc.<br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="auto" class=""><div class=""><div class="gmail-h5"><br class=""><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><div class="">That’s not to say we need totally distinct syntax. Deconstructing a value should visually relate to constructing it. So here’s how I think these two relate: a constructor is a function. Function signature has these arguments that the function refers to in its body. Pattern matching is the starting point of deconstructing a value. The scope created following it is the equivalent of a “body”, in which the associated values are used as “arguments”. Therefore it make sense to say that these labels are more like internal names (the 2nd “x” in the comment of the above sample).</div><div class=""><div class="gmail-m_-1761281494831127475h5"><div class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div dir="ltr" style="font-family:helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><div class=""><div class=""><span class="gmail-m_-1761281494831127475m_2305407596806730669gmail-"><blockquote type="cite" class=""><div class=""><div dir="ltr" style="font-family:helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><div class="gmail_extra"><div class="gmail_quote"><div class="">3.</div><div class="">The first part of the proposal aligns enum case syntax with functions. Functions often taken prepositions as argument labels, and indeed previous SE proposals have extended the rules to allow most words. However, `case foo(index: Int, in: T)` would have a disastrous label, as `in` would be a very annoying variable name whose use would be actively encouraged by the proposed sugared pattern matching rules.</div><div class=""><br class=""></div><div class="">The proposed rules for the sugared pattern would also require (well, greatly encourage) unique labels for each argument. This again is inconsistent with the naming conventions encouraged by the first part of the proposal aligning enum case syntax with functions, which have no such restrictions. If a user names something `case foo(point: T, point: T)`, then the matching rules would actively encourage an invalid redefinition of a variable named `point`.</div><div class=""><br class=""></div><div class="">(On the other hand, the API author does not have the luxury of naming the same case `foo(from point: T, to point: T)`, and even if they did, prepositions can make lousy local variable names--see first paragraph.)</div></div></div></div></div></blockquote><div class=""><br class=""></div></span>I don’t see this as a problem for enum case authors. It just means the poor pattern writer needs to provide the positional information to disambiguate.</div></div></div></div></blockquote><div class=""><br class=""></div><div class=""> What do you mean by "positional information" here?</div><div class=""><br class=""></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><div class=""><div class=""><span class="gmail-m_-1761281494831127475m_2305407596806730669gmail-"><blockquote type="cite" class=""><div class=""><div dir="ltr" style="font-family:helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><div class="gmail_extra"><div class="gmail_quote"><div class="">4.</div><div class="">The proposal does not explore what happens when the proposed prohibition on "mixing and matching" the proposed sugared and unsugared pattern matching runs up against associated values that have a mix of labeled and unlabeled parameters, and pattern matching user cases where the user does not wish to bind all of the arguments.</div><div class=""><br class=""></div><div class="">Given `case foo(a: Int, String, b: Int, String)`, the only sensible interpretation of the rules for sugared syntax would allow the user to choose any name for some but not all of the labels. If the user wishes to bind only `b`, however, he or she will need to navigate a puzzling set of rules that are not spelled out in the proposal:</div><div class=""><br class=""></div><div class="">```</div><div class="">case foo(a: _, _, b: let b, _)</div><div class="">// this is definitely allowed</div><div class=""><br class=""></div><div class="">case foo(a: _, _, b: let myVar, _)</div><div class="">// this is also definitely allowed</div><div class=""><br class=""></div><div class="">// but...</div><div class=""><div class="">case foo(_, _, b: let myVar, _)</div><div class="">// is this allowed, or must the user explicitly state and not bind `a`?</div></div><div class=""><br class=""></div><div class="">// ...and with respect to the sugared version...</div><div class="">case foo(_, _, let b, _)</div><div class="">// is this allowed, or must the user explicitly state and not bind `a`?</div><div class="">```</div><div class=""><br class=""></div></div></div></div></div></blockquote><div class=""><br class=""></div></span><div class="">Good point. To make up for this: `_` can substitute any sub pattern, which is something that this proposal doesn’t change but definitely worth spelling out. </div><span class="gmail-m_-1761281494831127475m_2305407596806730669gmail-"><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" style="font-family:helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><div class="gmail_extra"><div class="gmail_quote"><div class="">5.</div><div class="">In the "update and commentary" revising SE-0111, the core team outlined a preferred path to restoring the full use of argument labels for functions without giving them type system significance. They gave a non-sugared form and a sugared form, both of which have met with approval from the community.</div><div class=""><br class=""></div><div class="">Briefly, the non-sugared form allows compound names to be used in variable names: `<span style="white-space:pre-wrap" class="">func foo(opToUse op(lhs:rhs:) : (Int, Int) -> Int)`. </span>The first part of this proposal is consistent in that it removes the type system significance of argument labels from the associated values of enum cases, and considers them as part of the enum case name. It also stands to reason that, if a user were to match a case _without_ trying to bind any variables, the same syntax would have be used if the base name is ambiguous: `case elet(locals:body:): break`.</div><div class=""><br class=""></div><div class="">However, the proposal makes no provision for using that same compound name in pattern matching. There appears to be no particular reason for its isolated omission here, as `case elet(locals:body:)(let a, let b): return a * b` is readable and presents no syntactic difficulties. (Moreover, it is consistent with the syntax permitted in this proposal for initializing a variable: `let foo = Expr.elet(locals:body:)([], anExpr)`.)</div></div></div></div></div></blockquote><div class=""><br class=""></div></span><div class="">Another good point. We can handle this in the purely additional proposal for compound variable names. I consider this not the 5th item in the list, but a separate suggestion, however :P</div><span class="gmail-m_-1761281494831127475m_2305407596806730669gmail-"><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" style="font-family:helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""><br class=""></div><div class="">--- </div><div class=""><br class=""></div><div class="">In light of these shortcomings, I would argue that the following alternative scheme is the most intuitive and consistent for pattern matching given the general agreement that enum case representation should be "normalized":</div><div class=""><br class=""></div><div class="">Given:</div><div class=""><br class=""></div><div class="">```</div><div class="">enum S {</div><div class=""> <span class="gmail-m_-1761281494831127475m_2305407596806730669Apple-converted-space"> </span>case foo(bar: Int, baz: Int)</div><div class=""> <span class="gmail-m_-1761281494831127475m_2305407596806730669Apple-converted-space"> </span>case foo(boo: String)</div><div class=""> <span class="gmail-m_-1761281494831127475m_2305407596806730669Apple-converted-space"> </span>case bar(boo: String)</div><div class="">}</div><div class="">```</div><div class=""><br class=""></div><div class="">a. As in functions after SE-0111, enum cases can be identified unambiguously, regardless of whether one is initializing a variable or matching a case, by their compound name, e.g. `bar(boo:)`. Where a case can be unambiguously identified with only the base name, that is an alternative spelling, e.g. `bar`. Where a case cannot be identified uniquely with the base name, then it is an error to try to use the base name alone: `case foo: break // error: unambiguous`.</div><div class=""><br class=""></div><div class="">b. As in functions after SE-0111, arguments can be passed in either a sugared form or an unsugared form, and they can be bound in a pattern matching statement in the same way. That is, `case foo(bar: let a, baz: let b): break` and `case foo(bar:baz:)(let a, let b): break` are equivalent.</div><div class=""><br class=""></div><div class="">c. As in functions, one cannot supply different or incorrect argument labels. That is, `case foo(baz: let a, bar: let b)` and `case foo(baz:bar:)(let a, let b)` are both forbidden. _This recovers the vast majority of the additional syntactic safety that is outlined in the revised proposal, but without the use of any special rules for pattern matching._</div><div class=""><br class=""></div><div class="">d. By composing rules (a) and (b), `case bar(let a)` is allowed as it is today, preserving source compatibility. However `case foo(let b, let c)` is not allowed, and _not_ because different local variable names are chosen, but because the enum has two cases named foo.</div></div></div></div></div></blockquote><div class=""><br class=""></div></span>From a user’s point of view, there’s enough positional information in this pattern for the compiler to figure out which case it should match. This would be very unintuitive IMO.</div></div></div></div></blockquote><div class=""><br class=""></div><div class="">Wait, the key point of your proposal, with its "stricter rules," is that labels shouldn't be optional even with sufficient positional information! That's also the whole thing above about getting us closer to aligning with SE-0111, etc.</div></div></div></div></div></blockquote><div class=""><br class=""></div></div></div>Fair enough. The argument I invoked leads us to a dark path :P<span class=""><br class=""><div class=""><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><span style="font-family:helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline" class="">______________________________<wbr class="">_________________</span><br style="font-family:helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><span style="font-family:helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline" class="">swift-evolution mailing list</span><br style="font-family:helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><a href="mailto:swift-evolution@swift.org" style="font-family:helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" target="_blank" class="">swift-evolution@swift.org</a><br style="font-family:helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" style="font-family:helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" target="_blank" class="">https://lists.swift.org/mailma<wbr class="">n/listinfo/swift-evolution</a></div></blockquote></span></div><br class=""></div></blockquote></div><br class=""></div></div>
</div></blockquote></div></div></div></blockquote></div><br class=""></div></div>
</div></blockquote></div><br class=""></body></html>