Hi all, I thought I’d chime in with my own 2c…
I’d probably prefer something more like “final” and vs non-final. It’s the concept we’re dancing around - can you add something to extend it? In which case, final would allow exhaustive use, and non-final would require handling the default case. Currently all Swift API would convert as “final”, and all imported Obj-C API (with perhaps exceptions) would import as is and require a default handling case. This negates the open vs public issue. But it does also mean that it would become a manual issue inside the module to mark the API as final to allow exhaustive switches, unless we say “exhaustive switches allowed on internal/fileprivate/private types”. Unsure how this plays into the web of things, though… Thanks, Rod > On 11 Aug 2017, at 9:41 am, Jordan Rose via swift-evolution > <swift-evolution@swift.org> wrote: > > > >> On Aug 10, 2017, at 13:00, David Hart <da...@hartbit.com >> <mailto:da...@hartbit.com>> wrote: >> >> >> >> On 10 Aug 2017, at 19:19, Jordan Rose <jordan_r...@apple.com >> <mailto:jordan_r...@apple.com>> wrote: >> >>> >>> >>>> On Aug 9, 2017, at 22:46, David Hart <da...@hartbit.com >>>> <mailto:da...@hartbit.com>> wrote: >>>> >>>> >>>>> On 10 Aug 2017, at 02:42, Jordan Rose <jordan_r...@apple.com >>>>> <mailto:jordan_r...@apple.com>> wrote: >>>>> >>>>> :-) As you've all noted, there are some conflicting concerns for the >>>>> default: >>>>> >>>>> - Source compatibility: the existing behavior for an unannotated enum is >>>>> "closed". >>>>> - Intuition: if you show someone an enum without an explicit annotation, >>>>> they'll probably expect they can switch over it. (I'm going to say this >>>>> is why Zach calls it a "sensible default".) >>>>> - Consistency: switches on an enum in the same module can always be >>>>> exhaustive, so having it be different across modules is a bit annoying. >>>>> (But 'public' already acts like this.) >>>>> >>>>> vs. >>>>> >>>>> - Library evolution: the default should promise less, so that you have >>>>> the opportunity to change it. >>>>> - Flexibility: you can emulate an exhaustive switch with a non-exhaustive >>>>> switch using fatalError, but not the other way around. >>>>> >>>>> All of this is why I suggested it be an explicit annotation in either >>>>> direction, but Matthew brought up the "keyword soup" problem—if you have >>>>> to write (say) "public finite enum" and "public infinite enum", but would >>>>> never write "private finite enum" or "private infinite enum", something >>>>> is redundant here. Still, I'm uncomfortable with the default case being >>>>> the one that constrains library authors, so at least for binary >>>>> frameworks (those compiled "with resilience") I would want that to be >>>>> explicit. That brings us to one more concern: how different should binary >>>>> frameworks be from source frameworks? >>>> >>>> In terms of intuition and consistency, I think we should really try to >>>> learn from the simplicity of public/open: >>>> >>>> * When internal, classes are sub-classable by default for convenience, but >>>> can be closed with the final keyword >>>> * When public, classes are closed to sub-classing for safety, but can be >>>> opened up with the open keyword (which implies public). >>>> >>>> If we try to mirror this behaviour (the keywords are just suggestions, not >>>> important): >>>> >>>> * When internal, enums are exhaustive by default for convenience, but can >>>> be opened-up with the partial keyword >>>> * When public, enums are non-exhaustive by default for safety, but can be >>>> made exhaustive with the exhaustive keyword (which implies public). >>> >>> This is not a correct understanding of the internal/public distinction for >>> classes, though. From inside a module, a public-but-not-open class is still >>> subclassable, and similarly a public-but-not-"closed" enum will still be >>> exhaustively switched. You don't have to worry about your own module >>> changing out from under you. >> >> Correct. Thanks for the clarification! But you still agree with the >> argument, right? Convenience for same module enums (exhaustive by default), >> safety for clients of the module (not-exhaustive when public from outside >> the module), with the option to be explicit? > > That's the "library evolution" criterion above, yes. But the behavior of > enums inside the module doesn't need to affect what we do across modules. > >> And what do you think of the idea of having the « exhaustiveness » modifier >> imply public, like open does? > > I'm a little less sure about that. It does help with the keyword soup > problem, but it's also not as obviously about access as "open" was, and > "open" can also appear where other access modifiers can appear (on methods, > properties, and subscripts). > > Jordan > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org <mailto:swift-evolution@swift.org> > https://lists.swift.org/mailman/listinfo/swift-evolution > <https://lists.swift.org/mailman/listinfo/swift-evolution>
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution