On Thu, Apr 20, 2017 at 3:20 PM, John McCall via swift-evolution < [email protected]> wrote:
> Proposal Link: https://github.com/apple/swift-evolution/blob/ > master/proposals/0155-normalize-enum-case-representation.md > > Hello Swift Community, > > The review of SE-0155 "Normalize Enum Case Representation” ran from March > 31st through April 10th, 2017. The proposal is *accepted with revisions*. > > 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. > > 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. > > It is true that including associated-value labels in case patterns does > preserve a great deal of information in the source code: > > - This information can usefully contribute to the clarity of the code > following the pattern. > > - 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. > > - 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. > > However, the core team feels that there are counter-arguments which weaken > the force of these considerations: > > - 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. > > - 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. > > - 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 *are* 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. > > Accordingly, while it needs to be *possible* to include associated value > labels in a case-pattern, and in some situations it may be *wise* 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: > > 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: > > enum E { > case often(first: Int, second: Int) > case lots(first: Int, second: Int) > case many(value: Int) > case many(first: Int, second: Int) > case many(alpha: Int, beta: Int) > case sometimes(value: Int) > case sometimes(Int) > } > > switch e { > // Valid: the sequence of labels exactly matches a case name. > case .often(first: let a, second: let b): > ... > > // Valid: there is only one case with this base name. > case .lots(let a, let b): > ... > > // Valid: there is only one case with this base name and payload count. > case .many(let a): > ... > > // Invalid: there are multiple cases with this base name and payload > count. > case .many(let a, let b): > ... > > // Valid: the sequence of labels exactly matches a case name. > case .many(first: let a, second: let b): > ... > > // Invalid: includes a label, but not on all of the labelled arguments. > case .same(alpha: let a, let b): > ... > > // Valid: the sequence of labels exactly matches a case name (that > happens to not provide any labels). > case .sometimes(let x): > ... > > // Invalid: includes a label, but there is no matching case. > case .sometimes(badlabel: let x): > ... > } > > This only affects case patterns. Constructing a case always requires that > any associated value labels in the case name be provided. > > 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. > I assume that the following is obvious and the core team's intention, but it bears confirmation and being documented: ``` enum F { case many(first: Int, second: Int) case many(Int, Int) case withDefaultValue(Int, Int, Int=42) case withDefaultValue(first: Int, second: Int, third: Int=42) case withDefaultValue(first: Int, second: Int, notThirdToMakeAPoint: Int=43) } switch f { // Valid, even though multiple cases have this base name and arity, // because it is an exact match for a case that provides no labels. case .many(let a, let b): break // Invalid, as case pattern must include even values with default. case .withDefaultValue(let a, let b): break // Valid, as inclusion doesn't mean binding. case .withDefaultValue(let a, let b, _): break // Valid, for the same reason as above. case .withDefaultValue(first: let a, second: let b, third: _): break // Invalid, because the label is part of what's required, even if using `_`, // since otherwise it could be ambiguous as to which case is being matched. case .withDefaultValue(first: let a, second: let b, _): break } ``` 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. > > John McCall > Review Manager > > _______________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution > >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
