<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 4:39 PM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" class="">xiaodi.wu@gmail.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">On Thu, Apr 20, 2017 at 3:20 PM, John McCall via swift-evolution <span dir="ltr" class="">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt;</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:&nbsp;<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&nbsp;March 31st through April 10th, 2017. The proposal is&nbsp;<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.&nbsp; However, there was substantial disagreement about the right direction for pattern matching.&nbsp; 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.&nbsp; 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.&nbsp; 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.&nbsp; 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="">&nbsp; - This information can usefully contribute to the clarity of the code following the pattern.</div><div class=""><br class=""></div><div class="">&nbsp; - Hiding this information can lead to bugs that would be self-evident if the case labels were always included.&nbsp; 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="">&nbsp; - 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="">&nbsp; - 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.&nbsp; This binding name can convey at least as much information as a label would.</div><div class=""><br class=""></div><div class="">&nbsp; - The risk of mis-labelling an associated value grows as the number of associated values grows.&nbsp; However, very few cases carry a large number of associated values.&nbsp; 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.&nbsp; 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.&nbsp; 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="">&nbsp; - It is likely that cases will continue to be predominantly distinguished by their base name alone.&nbsp; Methods are often distinguished by argument labels because the base name identifies an entire class of operation with many possible variants.&nbsp; 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.&nbsp; Even when cases&nbsp;<i class="">are</i>&nbsp;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&nbsp;<b class="">possible</b>&nbsp;to include associated value labels in a case-pattern, and in some situations it may be&nbsp;<b class="">wise</b>&nbsp;to include them, the core team believes that requiring associated value labels would be unduly onerous.&nbsp; 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.&nbsp; 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.&nbsp; For example:</div><div class=""><br class=""></div><div class=""><font face="Menlo" class="">&nbsp; enum E {</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; case often(first: Int, second: Int)</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; case lots(first: Int, second: Int)</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; case many(value: Int)</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; case many(first: Int, second: Int)</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; case many(alpha: Int, beta: Int)</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; case sometimes(value: Int)</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; case sometimes(Int)</font></div><div class=""><font face="Menlo" class="">&nbsp; }</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">&nbsp; switch e {</font></div><div class=""><font face="Menlo" class="">&nbsp; // Valid: the sequence of labels exactly matches a case name.</font></div><div class=""><font face="Menlo" class="">&nbsp; case .often(first: let a, second: let b):</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; ...</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">&nbsp; // Valid: there is only one case with this base name.</font></div><div class=""><font face="Menlo" class="">&nbsp; case .lots(let a, let b):</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; ...</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">&nbsp; // Valid: there is only one case with this base name and payload count.</font></div><div class=""><font face="Menlo" class="">&nbsp; case .many(let a):</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; ...</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">&nbsp; // Invalid: there are multiple cases with this base name and payload count.</font></div><div class=""><font face="Menlo" class="">&nbsp; case .many(let a, let b):</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; ...</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">&nbsp; // Valid: the sequence of labels exactly matches a case name.</font></div><div class=""><font face="Menlo" class="">&nbsp; case .many(first: let a, second: let b):</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; ...</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">&nbsp; // Invalid: includes a label, but not on all of the labelled arguments.</font></div><div class=""><font face="Menlo" class="">&nbsp; case .same(alpha: let a, let b):</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; ...</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">&nbsp; // 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="">&nbsp; case .sometimes(let x):</span></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; ...</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">&nbsp; // Invalid: includes a label, but there is no matching case.</font></div><div class=""><span style="font-family:menlo" class="">&nbsp; case .sometimes(badlabel: let x):</span></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; ...</font></div><div class=""><font face="Menlo" class="">&nbsp; }</font></div><div class=""><br class=""></div><div class="">This only affects case patterns.&nbsp; 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.&nbsp; 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="">&nbsp; case many(first: Int, second: Int)</div><div class="">&nbsp; case many(Int, Int)</div><div class="">&nbsp; case withDefaultValue(Int, Int, Int=42)</div><div class="">&nbsp; case withDefaultValue(first: Int, second: Int, third: Int=42)</div><div class="">&nbsp; 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="">&nbsp; 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="">&nbsp; 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="">&nbsp; 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="">&nbsp; 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="">&nbsp; break</div><div class="">}</div><div class="">```</div></div></div></div></div></blockquote><div><br class=""></div>Precisely on all counts.</div><div><br class=""></div><div><blockquote type="cite" class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><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="">&nbsp; break</div></div></div></div></blockquote><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""><br class=""></div><div class="">This would also be invalid even if it weren't ambiguous because you cannot selectively omit labels.</div><div class=""><br class=""></div><div class="">John.</div><div class=""><br class=""></div></div></div></div></div><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><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.&nbsp; The core team feels that imparting local variable names with this kind of significance would be unprecedented, surprising, and rather "pushy".&nbsp; The goal of this rule is also largely achieved by the new rule allowing labels to be omitted regardless of binding.&nbsp; Accordingly, this rule is struck from the proposal.&nbsp; 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></div><br class=""></body></html>