I am not convinced by these arguments, they seem to be a ‘poor man’s’ 
versioning system. For example consider:

    // In module. 
    public enum E {
        case A, B, C
    }

    // In application. 
    switch e {
    case A: a()
    default: d()
    unknown case: u()
    }

When e == B or C is u() or d() called? I would expect d() since the application 
programmer obviously intends to handle unexpected differently than default. 

Now when E is modified and case D added by the module programmer I would expect 
B and C to still call d() and D to call u(). 

To achieve the above behaviour the switch encodes that when it compiled default 
was for B and C and therefore D is the new case and therefore it calls u(). 

When the code is recompiled against the new module the behaviour changes. D 
will now call d(). This will be without a warning. Hence I am classing this as 
a ‘poor man’s’ module system. 

Possible solutions include:

  1. You can’t have a default with an extensible enum, but you must have a 
unknown case. This prevents handling default cases at all, you have to list all 
the existing cases separately. 

  2. As described above in 1 the unknown case does very little. Instead just 
use default and don’t introduce unknown. 

  3. Have a versioned module system that requires enum cases and matching 
switch statements to be versioned. EG:

    // In module. 
    @version(1) public enum E {
        case A, B, C
    }
    @version(1.6) public enum E {
        case A, C, D
    }

    // In application. 
    @version(1.5) switch e {
    case A: a()
    default: d()
    unknown case: u()
    }

The module system would have to publish which enum cases were available for 
each version including all old versions. Note how the above notation allows 
removal and addition of cases. 

-- Howard. 

> On 3 Jan 2018, at 12:26 am, Kelvin Ma via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
> 
> 
>> On Tue, Jan 2, 2018 at 11:45 PM, Nevin Brackett-Rozinsky via swift-evolution 
>> <swift-evolution@swift.org> wrote:
>>> On Tue, Jan 2, 2018 at 9:07 PM, Jordan Rose via swift-evolution 
>>> <swift-evolution@swift.org> wrote:
>>> [Proposal: 
>>> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md]
>>> 
>>> Whew! Thanks for your feedback, everyone. On the lighter side of 
>>> feedback—naming things—it seems that most people seem to like '@frozen', 
>>> and that does in fact have the connotations we want it to have. I like it 
>>> too.
>>> 
>>> More seriously, this discussion has convinced me that it's worth including 
>>> what the proposal discusses as a 'future' case. The key point that swayed 
>>> me is that this can produce a warning when the switch is missing a case 
>>> rather than an error, which both provides the necessary compiler feedback 
>>> to update your code and allows your dependencies to continue compiling when 
>>> you update to a newer SDK. I know people on both sides won't be 100% 
>>> satisfied with this, but does it seem like a reasonable compromise?
>>> 
>>> The next question is how to spell it. I'm leaning towards `unexpected 
>>> case:`, which (a) is backwards-compatible, and (b) also handles "private 
>>> cases", either the fake kind that you can do in C (as described in the 
>>> proposal), or some real feature we might add to Swift some day. `unknown 
>>> case:` isn't bad either.
>>> 
>>> I too would like to just do `unknown:` or `unexpected:` but that's 
>>> technically a source-breaking change:
>>> 
>>> switch foo {
>>> case bar:
>>>   unknown:
>>>   while baz() {
>>>     while garply() {
>>>       if quux() {
>>>         break unknown
>>>       }
>>>     }
>>>   }
>>> }
>>> 
>>> Another downside of the `unexpected case:` spelling is that it doesn't work 
>>> as part of a larger pattern. I don't have a good answer for that one, but 
>>> perhaps it's acceptable for now.
>>> 
>>> I'll write up a revision of the proposal soon and make sure the core team 
>>> gets my recommendation when they discuss the results of the review.
>>> 
>>> ---
>>> 
>>> I'll respond to a few of the more intricate discussions tomorrow, including 
>>> the syntax of putting a new declaration inside the enum rather than 
>>> outside. Thank you again, everyone, and happy new year!
>>> 
>>> Jordan
>> 
>> 
>> +1 to warning instead of error
>> +1 to unknown/unexpected case
>> +1 to “@frozen” or any other reasonable spelling, they are all fine by me.
> 
> +1 to “@tangled” because abi is complicated
>  
>> 
>> The one remaining problem to solve is making sure multi-module apps can 
>> leave out the unknown/unexpected case on enums from modules which are part 
>> of the app itself and thus cannot be updated independently of it. John 
>> McCall’s version-locking plan sounds promising, though we should explore the 
>> available options before finalizing a course.
>> 
>> Perhaps we need a concept of submodules, or supermodules, or some other way 
>> to demarcate the boundaries of a resilience domain.
>> 
>> Nevin
> 
> i would support a proper submodule system over some verson-locking system 
> that only the most advanced users will probably know about. i think modules 
> should be one level higher than what they’re currently being used for right 
> now for lack of a better alternative (one application should never have to 
> define more than one capital M Module). submodules shouldn’t be that hard to 
> implement, though the submodule names should be part of ABI to avoid name 
> mangling problems
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to