[swift-evolution] [draft] Compound Names For Enum Cases
Xiaodi Wu
xiaodi.wu at gmail.com
Tue Jan 24 21:10:15 CST 2017
No code would be broken. Like functions, case `bar(a:)` can be referred to
as `bar` as long as there is no ambiguity. No existing code can have more
than one case named bar.
On Tue, Jan 24, 2017 at 19:17 Christopher Kornher <ckornher at me.com> wrote:
> Sorry for not connecting the dots…yet another example of why we need a
> better way to handle long discussions :)
> …and the dangers of multitasking, perhaps…
>
> I guess that this shows that having multiple cases with the same name,
> distinguished by the type of associated value, is possible without this
> proposal, for whatever that may be worth.
>
> It is anecdotal, perhaps, but this proposal will break a lot of my code. I
> tend to use labels as public names for associated values, and different
> internal names. Forcing consistent naming is sensible. It would come at the
> cost of breaking a significant amount of existing code and making the
> language more “fiddly”.
>
> Comparisons have been made to function signatures, but enums cases with >
> 2 values are rare in my experience, and functions can often have > 2
> arguments. Perhaps enums with more associated values will become more
> common if enum cases become more like structure declarations with well
> defined element names.
>
> Just a random thought: Treating enum cases like structs would become more
> reasonable as a result of this proposal i.e. they could conform to
> protocols. I am not sure that anyone wants to worry about functions for
> enum cases, but it might be useful to pass enum cases directly to functions
> that would normally need a struct. Unifying enums and structs in this way
> might an interesting thing to consider.
>
> Associated values that can differ for each enum case seems to be a feature
> unique to Swift. Is this a feature of any other language?
>
> On Jan 24, 2017, at 4:55 PM, Xiaodi Wu via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> Yes, but *this* proposal is precisely to make the label part of the name.
>
>
> On Tue, Jan 24, 2017 at 17:51 Christopher Kornher <ckornher at me.com> wrote:
>
> On Jan 24, 2017, at 4:24 PM, Xiaodi Wu via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> I'm now confused who is arguing for what. Enums cases cannot have the same
> name. As far as I'm aware, this proposal does not seek to change that. Each
> case must still be unique. It only changes whether labels are regarded as
> part of the name or part of the associated type.
>
>
> Labels are currently neither part of the name nor part of the associated
> type. See my example (it runs in the playground in Xcode 8.2.1).
>
> Forgive any lack of precise terminology: Labels for enums with associated
> values are currently only used to create a "function signature" for
> constructing values for the enum. They are ignored in all other uses of the
> enum AFAIK.
>
> My proposal is a way to allow multiple cases with the same name without
> breaking existing code. It has the benefit of giving enums a richer
> meaning, in simple English:
>
> Here is an example of a way to handle this currently and what it would
> become:
>
> // Runs now
> enum MultipleTypes {
> case anInt( value: Int )
> case aString( value: String )
> }
>
> enum E {
> case a( a: MultipleTypes )
> }
>
> let theCurrentWay = E.a( a: .aString( value: "str") )
>
> switch theCurrentWay {
> case .a( let x ) :
> switch x {
> case .anInt( let x ) :
> break
>
> case .aString( let x ) :
> break
> }
> }
>
> // Proposed:
>
> /*
> enum theNewWay {
> case a( value: Int ) :
> case a( value: String ) :
> }
>
> switch theCurrentWay {
> case .a( let x: Int ) :
> break
>
> case .a( let x: String ) :
> break
> }
> */
>
>
>
>
> On Tue, Jan 24, 2017 at 17:16 Christopher Kornher via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> On Jan 24, 2017, at 4:02 PM, Daniel Duan <daniel at duan.org> wrote:
>
>
>
> Daniel Duan
> Sent from my iPhone
>
> On Jan 24, 2017, at 2:53 PM, Daniel Duan via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>
>
> Daniel Duan
> Sent from my iPhone
>
> On Jan 24, 2017, at 2:18 PM, Christopher Kornher via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> I agree that this rule would be consistent with the handing of Swift
> function signatures, but my proposal is self-consistent and:
>
> 1) It is more powerful, matching on the case name or not as required.
> 2) Is consistent with existing switches that ignore associated values
> 3) Is constant with ignored labels in other Swift constructs (proposed and
> in past versions of Swift, at least)
> 4) Avoids a possible API change for current enums. This is currently legal
> but would not be if the enum case “name” is the entire signature for
> constructing it:
>
> ```
> enum E {
> case a( a: Int )
> case b( a: Int )
> }
>
> let anEmum = E.a( a: 4 )
>
>
> switch anEmum {
> case .a( let x ) :
> break
> case .b( let x ) :
> break
> }
>
> switch anEmum {
> case .a( let y ) :
> break
>
> case .b( let y ) :
> break
> }
> ```
> So is this proposal worth creating a breaking change? I don’t think so.
> it would be possible to ignore the associated parameter name, but not the
> type, but that would further confuse case matching, I believe.
>
> I personally don’t see much purpose in having two enum cases with the same
> name if they are always treated as distinct and there is no way to reason
> on the case name.
>
>
> Would you say the same for functions? Our opinions differ in what
> constitute a "name". In Swift, function names include parameters. Each enum
> case declares a function that creates a enum value. That's why it's *more*
> consistent for enum to have a similar definition of "name".
>
> As for pattern matching, number of patterns the number of cases being
> matched have a many-to-one relationships. This is true in Swift and many
>
>
> (Ah, accidentally sent it on my iPhone. My apologies.)
>
> … other languages. What you are proposing complicates the rules by making
> this untrue. We'd have to special-case this feature in our pattern matching
> algorithm.
>
>
> I am not proposing a breaking change. I believe that it is the best way to
> handle “overloading” enum names without breaking existing code. I don’t
> believe that this proposal changes any existing logic or rules.
>
> The use of the terms "name” and "signature" is well established in many
> languages. e.g.: https://en.wikipedia.org/wiki/Type_signature I am trying
> to use the terms in this context.
>
> Sharing a function name (with different signatures) is an aid to
> understanding the purpose of functions and is part of many languages. I do
> not believe that extending the concept to enums is worth the cost,
> especially since it will break existing Swift code.
>
> You are proposing a source breaking change and I do not agree that is is
> an improvement. What is the benefit of this change?
>
>
>
> If they are always distinct, then requiring different names eliminates
> unnecessary cognitive load. There is a good reason for functions to have
> the same “name” and different signatures, and there are precedents in many
> languages.
>
> You may disagree, but I believe that enums exist to support reasoning on
> distinct cases and that muddying that by treating the associated value as
> part of the “signature" increases the language “surface area” while adding
> no tangible benefit.
>
>
> On Jan 24, 2017, at 2:23 PM, Matthew Johnson via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>
> On Jan 24, 2017, at 3:10 PM, Christopher Kornher via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> Your example is only has only one case, which is not typical. Perhaps I am
> missing something, but the only reason that I can imagine for having a case
> with multiple ways to “construct” it is to have all variants of the case to
> match. If you don’t want them to match, use a different case name.
>
>
> It sounds like you are missing something. The `bar(a:)` and `bar(b:)` are
> the full case names. These are *not* the same case. The `bar` shorthand
> is allowed when there is no ambiguity, however for an enum with both
> `bar(a:)` and `bar(b:)` there *is* ambiguity and therefore the `bar`
> shorthand is not allowed. The programmer is required to spell out the full
> name of the case they wish to match.
>
>
>
> It would still be possible to match on the different types of bar when
> needed:
>
> ```
> enum Foo {
> case bar(a: Int)
> case bar(b: String)
> case notAbar
> }
>
>
> switch aFoo {
> case .bar( let a: Int) : // matches Ints only
> ...
>
> case .bar( let b: String) : // matches Strings only
> ...
> }
>
> switch aFoo {
> case .bar : // Matches both cases and that is a good thing
> …
>
> case notAbar:
> ….
> }
>
> ```
>
> On Jan 24, 2017, at 5:27 AM, Xiaodi Wu via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> I would imagine it would be logical to have it work just like it does now
> with functions. If case bar is distinct, then that should still work, but
> if bar is "overloaded," then case bar should be invalid for ambiguity.
> Seems fine to me, shouldn't break any existing code and therefore we don't
> lose anything.
>
>
> On Tue, Jan 24, 2017 at 01:13 David Hart via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>
>
> On 24 Jan 2017, at 00:52, Joe Groff via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> We're not terribly principled about this right now with non-pattern
> declaration references. You can still reference an unapplied function by
> its base name alone without its labels, if it's unambiguous:
>
> func foo(x: Int, y: Int) {}
>
> let foo_x_y: (Int, Int) -> () = foo
>
>
> so it'd be consistent to continue to allow the same in pattern references.
>
>
> WRT ambiguity, do we loose the ability to pattern match on the naked case
> name when two cases share the same base name?
>
> enum Foo {
> case bar(a: Int)
> case bar(b: String)
> }
>
> switch aFoo {
> case .bar: // matches both cases
> break
> }
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> _______________________________________________
> 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/20170125/cff2b63a/attachment.html>
More information about the swift-evolution
mailing list