[swift-dev] [swift-evolution] Re-pitch: Deriving collections of enum cases

Brent Royal-Gordon brent at architechies.com
Sun Nov 12 04:54:02 CST 2017

> On Nov 10, 2017, at 11:01 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
> Nit: if you want to call it `ValueEnumerable`, then this should be `DefaultValueCollection`.

I used `DefaultCaseCollection` because, although the protocol can work with any type to return its values, this type can only work with enums and only returns their cases. `ValueEnumerable` could be sensibly applied to `Int`; `DefaultCaseCollection` could not.

> More generally though, I can see the appeal of allowing `Int` to conform to `ValueEnumerable`, but I've got a feeling that this is headed rapidly in the direction of overengineering a feature without a good rationale for the additional complexity. The stated use case is to enumerate the cases of an enum, and any additional complexity above that should stand on its own merit. I disagree quite vehemently that protocols should be "as general as possible"; rather, they exist to enable useful generic algorithms and should be as _useful_ as possible. There is a happy medium beyond which overengineering the design makes a protocol markedly less usable/approachable for the sake of enabling rare functionality.

Tony's "no more specific than they need to" language applies here. The way I see it is this:

* `Bool` is not an enum, but it could be usefully conformed to `ValueEnumerable`. Why should we prevent that?
* A type with two independently-switchable `Bool`s—say, `isMirrored` and `isFlipped`—could be usefully conformed to `ValueEnumerable`. Why should we prevent that?
* Having integer types conform to `ValueEnumerable` with `static let allValues = Self.min...Self.max` could be useful. Why should we prevent that?

And at the same time, a small, specialized collection type _also_ helps with our intended use case in some ways (while admittedly making things more difficult in others). So I think the more general design, which also works better for our intended use case, is the superior option.

> Along the lines of user ergonomics, I would advocate for as many enums as possible to conform without explicit opt-in. It's true that we are moving away from such magical designs, and for good reason, but the gain here of enums Just Working(TM) for such a long-demanded feature has, I would argue, more benefits than drawbacks. To my mind, the feature is a lot like `RawRepresentable` in several ways, and it would be defensible for an equal amount of magic to be enabled for it.

But `RawRepresentable` *doesn't* get automatically added to all enums—you explicitly opt in, albeit using a special sugar syntax. No, I think opt-in is the right answer here. We might be able to justify adding sugar to opt-in, but I can't actually think of a way to make opting in easier than conforming to a protocol and letting the complier synthesize the requirements.

(This is also important for library evolution. A public enum may not want to promise that its values will always be enumerable—for instance, it might add a case with a non-enumerable associated type in the future. Since conformances are always as public as the type itself, we can't have this feature be opt-out without moving away from using a protocol.)

Brent Royal-Gordon

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-dev/attachments/20171112/bf30fb40/attachment.html>

More information about the swift-dev mailing list