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…



> 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

Reply via email to