<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 20, 2017, at 5:50 PM, Goffredo Marocchi <<a href="mailto:panajev@gmail.com" class="">panajev@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="content-type" content="text/html; charset=utf-8" class=""><div dir="auto" class=""><div class="">One thing I wanted to point out and that was a non trivial issue last year and that the core team did discuss and agreed to revisit (if I remember the thread update by Chris Lattner last year):</div><div class=""><br class=""></div><div class=""><div style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class=""><br class="webkit-block-placeholder"></div><blockquote type="cite" class=""><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Note that since the labels aren't part of a tuple, they no longer participate in type checking, behaving consistently with functions.</span></p><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px;"><pre style="box-sizing: border-box; word-wrap: normal; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal;" class=""><font face="UICTFontTextStyleBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class=""><span class="pl-k" style="box-sizing: border-box;">let</span> f <span class="pl-k" style="box-sizing: border-box;">=</span> Expr.<span class="pl-smi" style="box-sizing: border-box;">elet</span> <span class="pl-c" style="box-sizing: border-box;"><span class="pl-c" style="box-sizing: border-box;">//</span> f has type ([(String, Expr)], Expr) -> Expr</span>
<span class="pl-c" style="box-sizing: border-box;"></span><span class="pl-c1" style="box-sizing: border-box;">f</span>([], anExpr) <span class="pl-c" style="box-sizing: border-box;"><span class="pl-c" style="box-sizing: border-box;">//</span> Okay!</span>
<span class="pl-c" style="box-sizing: border-box;"></span><span class="pl-c1" style="box-sizing: border-box;">f</span>(<span class="pl-c1" style="box-sizing: border-box;">locals</span>: [], <span class="pl-c1" style="box-sizing: border-box;">body</span>: anExpr) <span class="pl-c" style="box-sizing: border-box;"><span class="pl-c" style="box-sizing: border-box;">//</span> Won't compile.</span></span></font></pre></div></blockquote>I appreciate effort for consistency, but I hope this is not going to be used against the effort to bring labels in functions/stored closures/callbacks.</div></div></div></blockquote><div><br class=""></div>It will not. The issues are unrelated. Whatever rules we use for supporting argument labels on indirect calls to functions will also apply to indirect calls to enum case constructors.</div><div><br class=""></div><div>John.</div><div><br class=""><blockquote type="cite" class=""><div class=""><div dir="auto" class=""><div class="">Swift, as we discussed last year, made a conscious, intentional effort to double down on the self documentation and call site readability of argument labels in general and the status quo after Swift 3/3.1 is not reflecting that whenever functions are stored in variables and/or passed to other functions as arguments.</div><div class=""><br class=""></div><div class="">I would like not to miss the Swift 4.0 deadline for this and we should discuss it sooner rather than later. I brought this up here because, for consistency, we are doubling down on something we should really be discussing to improve in my opinion.</div></div></div></blockquote></div><div><blockquote type="cite" class=""><div class=""><div dir="auto" class=""><div class=""><br class=""></div><div class="">Sent from my iPhone</div><div class=""><br class="">On 20 Apr 2017, at 21:39, Xiaodi Wu via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div dir="ltr" class="">On Thu, Apr 20, 2017 at 3:20 PM, John McCall via swift-evolution <span dir="ltr" class=""><<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>></span> wrote:<br 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="">Proposal Link: <a href="https://github.com/apple/swift-evolution/blob/master/proposals/0155-normalize-enum-case-representation.md" target="_blank" class="">https://github.com/<wbr class="">apple/swift-evolution/blob/<wbr class="">master/proposals/0155-<wbr class="">normalize-enum-case-<wbr class="">representation.md</a><div class=""><div class=""><div class=""><br class=""></div><div class="">Hello Swift Community,</div><div class=""><br class=""></div><div class="">The review of SE-0155 "Normalize Enum Case Representation” ran from March 31st through April 10th, 2017. The proposal is <b class="">accepted with revisions</b>.</div><div class=""><br class=""></div><div class="">Feedback from the community was positive about most aspects of the proposal. However, there was substantial disagreement about the right direction for pattern matching. The core team discussed this issue in depth.</div><div class=""><br class=""></div><div class="">Pattern matching is central to the use of enum types. It's the only way you can use an enum value, besides general operations like passing it to a function or the special affordances for Optionals. Pattern matching is as central to enums as stored property access is to structs, and it's fair to be worried about anything that would make it substantially more onerous. Unconditionally requiring associated-value labels in case patterns would certainly do that, and several members of the core team expressed concern that it would be bad enough to discourage the use of associated-value labels completely — in effect, subverting the entire language feature being proposed.</div><div class=""><br class=""></div><div class="">It is true that including associated-value labels in case patterns does preserve a great deal of information in the source code:</div><div class=""><br class=""></div><div class=""> - This information can usefully contribute to the clarity of the code following the pattern.</div><div class=""><br class=""></div><div class=""> - Hiding this information can lead to bugs that would be self-evident if the case labels were always included. For example, if a case payload included a number of different boolean flags, it would be easy for a pattern to accidentally label them in the wrong order.</div><div class=""><br class=""></div><div class=""> - Finally, this information may be necessary in order to determine which case is being matched, since the proposal adds the ability to distinguish cases purely by the labels on associated values.</div><div class=""><br class=""></div><div class="">However, the core team feels that there are counter-arguments which weaken the force of these considerations:</div><div class=""><br class=""></div><div class=""> - While an associated-value label can indeed contribute to the readability of the pattern, the programmer can also choose a meaningful name to bind to the associated value. This binding name can convey at least as much information as a label would.</div><div class=""><br class=""></div><div class=""> - The risk of mis-labelling an associated value grows as the number of associated values grows. However, very few cases carry a large number of associated values. As the amount of information which the case should carry grows, it becomes more and more interesting to encapsulate that information in its own struct — among other reasons, to avoid the need to revise every matching case-pattern in the program. Furthermore, when a case does carry a significant number of associated values, there is often a positional conventional between them that lowers the risk of re-ordering: for example, the conventional left-then-right ordering of a binary search tree. Therefore this risk is somewhat over-stated, and of course the programmer should remain free to include labels for cases where they feel the risk is significant.</div><div class=""><br class=""></div><div class=""> - It is likely that cases will continue to be predominantly distinguished by their base name alone. Methods are often distinguished by argument labels because the base name identifies an entire class of operation with many possible variants. In contrast, each case of an enum is a kind of data, and its name is conventionally more like the name of a property than the name of a method, and thus likely to be unique among all the cases. Even when cases <i class="">are</i> distinguished using only associated value labels, it simply means that the corresponding case-patterns must include those labels; we should not feel required to force that burden on all other case-patterns purely to achieve consistency with this presumably-unusual style.</div><div class=""><br class=""></div><div class="">Accordingly, while it needs to be <b class="">possible</b> to include associated value labels in a case-pattern, and in some situations it may be <b class="">wise</b> to include them, the core team believes that requiring associated value labels would be unduly onerous. Therefore, the core teams revises the proposal as follows:</div><div class=""><br class=""></div><div class="">A case pattern may omit labels for the associated values of a case if there is only one case with the same base name and arity. A pattern must omit all labels if it omits any of them; thus, a case pattern either exactly matches the full name of a case or has no labels at all. For example:</div><div class=""><br class=""></div><div class=""><font face="Menlo" class=""> enum E {</font></div><div class=""><font face="Menlo" class=""> case often(first: Int, second: Int)</font></div><div class=""><font face="Menlo" class=""> case lots(first: Int, second: Int)</font></div><div class=""><font face="Menlo" class=""> case many(value: Int)</font></div><div class=""><font face="Menlo" class=""> case many(first: Int, second: Int)</font></div><div class=""><font face="Menlo" class=""> case many(alpha: Int, beta: Int)</font></div><div class=""><font face="Menlo" class=""> case sometimes(value: Int)</font></div><div class=""><font face="Menlo" class=""> case sometimes(Int)</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""> switch e {</font></div><div class=""><font face="Menlo" class=""> // Valid: the sequence of labels exactly matches a case name.</font></div><div class=""><font face="Menlo" class=""> case .often(first: let a, second: let b):</font></div><div class=""><font face="Menlo" class=""> ...</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""> // Valid: there is only one case with this base name.</font></div><div class=""><font face="Menlo" class=""> case .lots(let a, let b):</font></div><div class=""><font face="Menlo" class=""> ...</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""> // Valid: there is only one case with this base name and payload count.</font></div><div class=""><font face="Menlo" class=""> case .many(let a):</font></div><div class=""><font face="Menlo" class=""> ...</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""> // Invalid: there are multiple cases with this base name and payload count.</font></div><div class=""><font face="Menlo" class=""> case .many(let a, let b):</font></div><div class=""><font face="Menlo" class=""> ...</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""> // Valid: the sequence of labels exactly matches a case name.</font></div><div class=""><font face="Menlo" class=""> case .many(first: let a, second: let b):</font></div><div class=""><font face="Menlo" class=""> ...</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""> // Invalid: includes a label, but not on all of the labelled arguments.</font></div><div class=""><font face="Menlo" class=""> case .same(alpha: let a, let b):</font></div><div class=""><font face="Menlo" class=""> ...</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""> // Valid: the sequence of labels exactly matches a case name (that happens to not provide any labels).</font></div><div class=""><span style="font-family:menlo" class=""> case .sometimes(let x):</span></div><div class=""><font face="Menlo" class=""> ...</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""> // Invalid: includes a label, but there is no matching case.</font></div><div class=""><span style="font-family:menlo" class=""> case .sometimes(badlabel: let x):</span></div><div class=""><font face="Menlo" class=""> ...</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><br class=""></div><div class="">This only affects case patterns. Constructing a case always requires that any associated value labels in the case name be provided.</div><div class=""><br class=""></div><div class="">A case pattern must include patterns for all associated values of the case, even if the associated value has a default value. We may choose to relax this rule in a future release, or generally provide some sort of "..." syntax for indicating that there are associated values being ignored.</div></div></div></div></blockquote><div class=""><br class=""></div><div class="">I assume that the following is obvious and the core team's intention, but it bears confirmation and being documented:</div><div class=""><br class=""></div><div class="">```</div><div class="">enum F {</div><div class=""> case many(first: Int, second: Int)</div><div class=""> case many(Int, Int)</div><div class=""> case withDefaultValue(Int, Int, Int=42)</div><div class=""> case withDefaultValue(first: Int, second: Int, third: Int=42)</div><div class=""> case withDefaultValue(first: Int, second: Int, notThirdToMakeAPoint: Int=43)</div><div class="">}<br class=""></div><div class=""><br class=""></div><div class="">switch f {</div><div class="">// Valid, even though multiple cases have this base name and arity,</div><div class="">// because it is an exact match for a case that provides no labels.</div><div class="">case .many(let a, let b):</div><div class=""> break</div><div class=""><br class=""></div><div class="">// Invalid, as case pattern must include even values with default.</div><div class="">case .withDefaultValue(let a, let b):</div><div class=""> break</div><div class=""><br class=""></div><div class="">// Valid, as inclusion doesn't mean binding.</div><div class="">case .withDefaultValue(let a, let b, _):</div><div class=""> break</div><div class=""><br class=""></div><div class="">// Valid, for the same reason as above.</div><div class="">case .withDefaultValue(first: let a, second: let b, third: _):</div><div class=""> break</div><div class=""><br class=""></div><div class="">// Invalid, because the label is part of what's required, even if using `_`,</div><div class="">// since otherwise it could be ambiguous as to which case is being matched.</div><div class="">case .withDefaultValue(first: let a, second: let b, _):</div><div class=""> break</div><div class="">}</div><div class="">```</div><div class=""><br 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 style="word-wrap:break-word" class=""><div class=""><div class=""><div class=""></div><div class="">The proposal includes a rule inferring labels in case patterns from binding names. The core team feels that imparting local variable names with this kind of significance would be unprecedented, surprising, and rather "pushy". The goal of this rule is also largely achieved by the new rule allowing labels to be omitted regardless of binding. Accordingly, this rule is struck from the proposal. That said, it would be a good idea for the implementation to warn when a binding name matches the label for a different associated value.</div><div class=""><br class=""></div><div class="">John McCall</div><div class="">Review Manager</div></div></div></div><br class="">______________________________<wbr class="">_________________<br class="">
swift-evolution mailing list<br class="">
<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/<wbr class="">mailman/listinfo/swift-<wbr class="">evolution</a><br class="">
<br class=""></blockquote></div><br class=""></div></div>
</div></blockquote><blockquote type="cite" class=""><div class=""><span class="">_______________________________________________</span><br class=""><span class="">swift-evolution mailing list</span><br class=""><span class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a></span><br class=""><span class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br class=""></div></blockquote></div></div></blockquote></div><br class=""></body></html>