[swift-evolution] [Accepted] SE-0155: Normalize Enum Case Representation
Xiaodi Wu
xiaodi.wu at gmail.com
Thu Apr 20 15:39:18 CDT 2017
On Thu, Apr 20, 2017 at 3:20 PM, John McCall via swift-evolution <
swift-evolution at swift.org> 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
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170420/79cc67ab/attachment.html>
More information about the swift-evolution
mailing list