[swift-evolution] Draft Proposal: Declare variables in 'case' labels with multiple patterns
Andrew Bennett
cacoyi at gmail.com
Mon Jan 25 19:43:53 CST 2016
Thanks Jordan,
I wrote a few responses, mostly misinterpreting what you meant, in the end
I agree with you.
It's more consistent to have a let in front of each case label, so it's of
the form:
case <PATTERN>, <PATTERN>, <PATTERN>, ...:
Each pattern is self contained, individually defining whether it's:
* let .Case1(1,x), or
* .Case1(1, let x)
Yesterday I updated the proposal to state these changes to the existing
Swift grammar:
+ enum-case-pattern-list → enum-case-pattern |+
enum-case-pattern , enum-case-pattern-list+ pattern →
enum-case-pattern-list- pattern → enum-case-pattern
https://github.com/therealbnut/swift-evolution/blob/therealbnut-case-match/proposals/0023-declare-variables-in-case-labels-with-multiple-patterns.md
It seems that I accidentally already did what you proposed, because the
grammar was structured like you suggested.
I'll fix the examples in the proposal. It's certainly shorter to only add
`let` once, but it probably complicates the grammar and pairs the let with
the case rather than the pattern (which is inconsistent).
The relevant bits of the current grammar:
enum-case-pattern *→* type-identifier [opt] .
enum-case-name tuple-pattern [opt]
tuple-pattern *→* (tuple-pattern-element-list [opt])
tuple-pattern-element-list *→* tuple-pattern-element |
tuple-pattern-element ,
tuple-pattern-element-list
tuple-pattern-element *→* pattern
pattern *→* value-binding-pattern
value-binding-pattern *→* *var* pattern |
* let* pattern
On Tue, Jan 26, 2016 at 9:15 AM, Jordan Rose <jordan_rose at apple.com> wrote:
> +1 in general, but as a nitpick I think this should be
>
> case let .Case1(x, 2), let .Case2(2, x):
>
>
> because the patterns really are distinct. (In other words, it seems weird
> to me that "case let .Case1(x), .Case2(x)" is different from "case
> .Case2(x), let .Case1(x)".)
>
> Jordan
>
> On Jan 22, 2016, at 19:39, Andrew Bennett via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> Hi,
>
> I'd like to discuss declaring variables in case labels with multiple
> patterns. I've written a draft proposal, but I'd like to discuss it first
> before formally proposing anything.
>
>
> https://github.com/therealbnut/swift-evolution/blob/a137202e41588b71d3c0511cff85f82ec5f65629/proposals/0023-declare-variables-in-case-labels-with-multiple-patterns.md
>
> In short:
>
> switch value {
> case let .Case1(x, 2), .Case2(2, x):
> print(x)
> }
>
>
> The original proposal is here, it may need to adapt after discussion, so
> I'll try to keep the proposal at that link up-to-date.
>
> Thanks,
> Andrew
>
> Declare variables in 'case' labels with multiple patterns
>
> - Proposal: SE-0022
> <https://github.com/therealbnut/swift-evolution/blob/master/proposals/0023-declare-variables-in-case-labels-with-multiple-patterns.md>
> - Author(s): Andrew Bennett <https://github.com/therealbnut>
> - Status: *In Discussion*
> - Review manager: *Not In Review*
>
> Introduction
>
> In Swift 2, it is possible to match multiple patterns in cases. However
> cases cannot contain multiple patterns if the case declares variables.
>
> The following code currently produces an error:
>
> enum MyEnum {
> case Case1(Int,Float)
> case Case2(Float,Int)
> }
> switch value {
> case let .Case1(x, 2), .Case2(2, x):
> print(x)
> case .Case1, .Case2:
> break
> }
>
> The error is:
>
> `case` labels with multiple patterns cannot declare variables.
>
> This proposal aims to remove this error when each pattern declares the
> same variables with the same types.
>
> Motivation
>
> This change reduces repeditive code, and therefore reduces mistakes. It's
> consistent with multi-pattern matching when variables aren't defined.
> Proposed solution
>
> Allow case labels with multiple patterns to declare patterns by matching
> variable names in each pattern.
>
> Using the following enum:
>
> enum MyEnum {
> case Case1(Int,Float)
> case Case2(Float,Int)
> }
>
> These cases should be possible:
>
> case let .Case1(x, _), .Case2(_, x):
> case let .Case1(y, x), .Case2(x, y):
> case let .Case1(x), .Case2(x):
> case .Case1(let x, _), .Case2(_, let x):
>
> Detailed design
>
> Allow case labels with multiple patterns if the case labels match the
> following constraints:
>
> - All patterns declare exactly the same variables.
> - The same variable has the same type in each pattern.
>
> Therefore each pattern is able to produce the same variables for the case
> label.
> Impact on existing code
>
> This should have no impact on existing code, although it should offer many
> opportunities for existing code to be simplified.
> Alternatives considered
> Using a closure or inline function
>
> Code repitition can be reduced with one pattern per 'case' and handling
> the result with an inline function.
>
> func handleCases(value: MyEnum, apply: Int -> Int) -> Int {
> func handleX(x: Int) -> Int {
> return apply(x) + 1
> }
> let out: Int
> switch value {
> case .Case1(let x, 2):
> out = handleX(x)
> case .Case2(2, let x):
> out = handleX(x)
> case .Case1, .Case2:
> out = -1
> }
> return out
> }
>
> This syntax is much more verbose, makes control flow more confusing, and
> has the limitations of the what the inline function may capture.
>
> In the above example apply cannot be @noescape because handleX captures
> it.
>
> Also in the above example if out is captured and assigned by handleX then
> it must be var, not let. This can produce shorter syntax, but is not as
> safe; out may accidentally be assigned more than once, additionally out also
> needs to initialized (which may not be possible or desirable).
> Extending the fallthrough syntax
>
> A similar reduction in code repetition can be achieved if fallthrough
> allowed variables to be mapped onto the next case, for example:
>
> switch test {
> case .Case1(let x, 2):
> fallthrough .Case2(_, x)
> case .Case2(3, .let x):
> print("x: \(x)")
> }
>
> This is not as intuitive, is a hack, and fallthrough should probably be
> discouraged. It is much more flexible, a programmer could adjust the value
> of x before fallthrough. Flexibility increases the chances of programmer
> error, perhaps not as much as code-repitition though.
> _______________________________________________
> 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/20160126/5d7a94c3/attachment.html>
More information about the swift-evolution
mailing list