> On Feb 7, 2017, at 3:01 PM, Michael Ilseman via swift-evolution
> <[email protected]> wrote:
>
> BTW, this will likely be part of the eventual design of “open”/resilient
> enums ala
> https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums
> <https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums>.
> There, the goal is to reduce both ABI and source breakage caused by this sort
> of thing. It seems like for your purposes, you’re less inclined to care about
> ABI breakage than source breakage, though that may change in the future.
Source breakage is generally *desirable* in the context of switch statements
over the cases of an enum. This is why I am strongly opposed to the idea of
making open enums the default.
It feels like this would only be a desirable API contract for enums which it
would be unusual for user code to switch over. Any time user code might
reasonably switch over the cases it feels like the wrong API contract. How is
the user code supposed to handle the unknown future cases correctly?
I think it’s also worth asking the question: if user code is not supposed to
switch over the cases of the enum, why is the type exposed publicly as an enum
at all? This means the cases are only intended to be used by the user to
create values of the type. Maybe a better API design would be something like
the following:
public struct Foo {
private enum Value {
case foo1
case foo2(String)
}
private let value: Value
private init(_ value: Value) {
self.value = value
}
public static var foo1: Foo {
return Foo(.foo1)
}
public static func foo2(_ value: String) -> Foo {
return Foo(.foo2(value))
}
}
public func apiFunctionTakingFoo(_ foo: Foo) {}
// user code:
apiFunctionTakingFoo(.foo1)
apiFunctionTakingFoo(.foo2(""))
This provides the same syntactic convenience for users when constructing values
and allows adding new values (i.e. “cases”), retains the ability to use an enum
internally in the implementation, and intentionally prevents users from
switching over the open set of values in a fragile way (i.e. handling unknown
future values / cases in a `default` clause).
This requires some boilerplate but it feels like it may often be a better API
design when the library author is not willing to commit to the contract of a
closed enum. It feels like it should be unusual when a library author expects
users to switch over the cases, but also wants to add new cases in the future.
>
>
>
>> On Feb 7, 2017, at 7:12 AM, Tanner Nelson via swift-evolution
>> <[email protected] <mailto:[email protected]>> wrote:
>>
>> Hello Swift Evolution,
>>
>> I'd like to propose that a warning be emitted when default cases are omitted
>> for enums from other modules.
>>
>> What this would look like:
>>
>> OtherModule:
>> ```
>> public enum SomeEnum {
>> case one
>> case two
>> }
>>
>> public let global: SomeEnum = .one
>> ```
>>
>> executable:
>> ```
>> import OtherModule
>>
>> switch OtherModule.global {
>> case .one: break
>> case .two: break
>> ^~~~~ ⚠︎ Warning: Default case recommended for imported enums. Fix-it:
>> Add `default: break`
>> }
>> ```
>>
>> Why:
>>
>> Allowing the omission of a default case in an exhaustive switch makes the
>> addition of a new case to the enum a breaking change.
>> In other words, if you're exhaustively switching on an enum from an imported
>> library, the imported library can break your code by adding a new case to
>> that enum (which the library authors may erroneously view as an
>> additive/minor-bump change).
>>
>> Background:
>>
>> As a maintainer of a Swift framework, public enums have been a pain point in
>> maintaining semver. They've made it difficult to implement additive features
>> and have necessitated the avoidance of enums in our future public API plans.
>>
>> Related Twitter thread:
>> https://twitter.com/tanner0101/status/796860273760104454
>> <https://twitter.com/tanner0101/status/796860273760104454>
>>
>> Looking forward to hearing your thoughts.
>>
>> Best,
>> Tanner
>>
>> Tanner Nelson
>> Vapor
>> +1 (435) 773-2831
>>
>>
>>
>>
>>
>>
>>
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution