I really like the idea of making it opt in with the extensible keyword as opposed to opt out with final so this way there is no impact on existing code
> On Jun 30, 2016, at 16:15, Dan Appel <[email protected]> wrote: > > I've had a draft of a proposal lying around for a while which addresses > exactly this, but I haven't gotten around to sending it out for comments yet. > Link. > > Would appreciate if you guys took a look. > Dan Appel > > Pasted inline below > > Extensible Enums > Proposal: SE-NNNN > Author: Dan Appel > Status: Awaiting review > Review manager: TBD > Introduction > > This proposal introduces a new keyword that can be applied to enums which > allows new cases to be introduced in extensions. > > Swift-evolution thread: [RFC] Extensible Enums > > Motivation > > Enums are a powerful feature which provides a lot of benefit if you have a > limited number of behaviors. For example, associated values provide the > ability to make every case essentially a separate type. However, due to the > static nature of enums, they cannot be used in situations where they would > otherwise be a perfect fit. > > An example of this would be the use of an Error enum like so: > > enum FileError: ErrorProtocol { > case fileNotFound(path: String) > case corruptedFile(bytes: [Int8]) > } > func readFile() throws { ... } > > // elsewhere in the codebase > do { > try readFile() > } catch let error as FileError { > switch error { > case .fileNotFound(let path): // handle error > case .corruptedFile(let bytes): // handle error > } > } catch { ... } > While this is generally a good approach, it can be very dangerous for library > consumers if the author exposes the error to the user. This is due to the > fact that the switch statement has to be exhaustive and is only satisfied > when all enum cases have been accounted for. What this means for library > authors is that every time they add a new case to a public enum, they are > breaking the exhaustivity of the switch and making their library > backwards-incompatible. > > Currently, the best workaround is to use a struct with static instances and > overloading the ~= operator. This allows for similar switch behavior but > overall is much less flexible, missing key features such as associated values. > > Another example is when the library is split into multiple modules, where the > error is defined in the first module and the second module wants to add some > error cases. An enum is very rarely used in this case because you cannot add > cases in other modules. Instead, library authors either use an error > protocol, and add more types that conform to it, or use the struct approach > shown above. While this is not terrible, adding cases in extensions would > better translate the intention of the author and adds more flexiblity. > > Proposed solution > > The solution proposed is quite simple: add an extensible keyword/modifier > that can be applied to enums, which would require the default case when > switched on and allow new cases to be added in extensions. > > Here is the translation of the very first example to the use an extensible > enum instead, with a new case added: > > extensible enum ThingError: ErrorProtocol { > case fileNotFound(path: String) > case corruptedFile(bytes: [Int8]) > case failedReadingFile > } > func readFile() throws { ... } > > // elsewhere in the codebase > do { > try readFile() > } catch let error as ThingError { > switch error { > case .fileNotFound(let path): // handle error > case .corruptedFile(let bytes): // handle error > default: // handle future errors that don't exist yet > } > } catch { ... } > For the second example, we can simply extend the enum in the higher-level > module. > > // Module FileProtocol > > extensible enum FileError: ErrorProtocol { > case fileNotFound(path: String) > } > > protocol FileProtocol { > func read() throws > } > > // Module File > > extension FileError { > case corruptedFile(bytes: [Int8]) > case failedReadingFile > } > > struct File: FileProtocol { > func read() throws { ... } > } > Detailed design > > A new keyword would be added to the language which is only allowed in front > of the enum keyword. When an enum is marked extensible, new cases can be > added in extensions and switches that are performed on it require a > defaultcase. > > Impact on existing code > > There is no impact on existing code since this is purely an additive feature. > > Alternatives considered > > No alternatives have been considered (yet). > > > > >> On Thu, Jun 30, 2016 at 1:04 PM David Sweeris via swift-evolution >> <[email protected]> wrote: >> By itself, this would break switch statements, since they have to be >> exhaustive. >> >> If anyone has any ideas about how to fix that, I'm all ears. >> >> - Dave Sweeris >> >> > On Jun 30, 2016, at 14:58, Edward Valentini via swift-evolution >> > <[email protected]> wrote: >> > >> > >> > I am finding myself in a situation where the most elegant "swifty" >> > solution would be to allow enum extensions to add to existing case >> > options. For example lets say I'm using a library that has the following >> > enum defined: >> > >> > enum MyDirection { >> > case east, west >> > } >> > >> > My app for example also makes use of north and south, so I would love to >> > be able to write: >> > >> > extension MyDirection { >> > case north,south >> > } >> > >> > In objective c, one would probably have defined constants like >> > MyDirectionEast etc... these would probably have been mapped to ints or >> > strings so a consumer of this library could have easily extended this to >> > add additional functionality, but using constants like that is not very >> > "swifty" >> > >> > I'm curious what the swift community thinks. >> > >> > Thank you >> > _______________________________________________ >> > 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 > > -- > Dan Appel
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
