<div dir="ltr">On Sun, Nov 12, 2017 at 4:54 AM, Brent Royal-Gordon <span dir="ltr">&lt;<a href="mailto:brent@architechies.com" target="_blank">brent@architechies.com</a>&gt;</span> wrote:<br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space"><div><span class=""><blockquote type="cite"><div>On Nov 10, 2017, at 11:01 PM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank">xiaodi.wu@gmail.com</a>&gt; wrote:</div><br class="m_-731029454393875740Apple-interchange-newline"><div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">Nit: if you want to call it `ValueEnumerable`, then this should be `DefaultValueCollection`.</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"></div></div></blockquote><div><br></div></span><div>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.</div></div></div></blockquote><div><br></div><div> Because of how you&#39;ve chosen to implement `DefaultCaseCollection`, or do you mean to say that you deliberately want a design where types other than enums do not share the default return type?</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space"><div><span class=""><blockquote type="cite"><div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">More generally though, I can see the appeal of allowing `Int` to conform to `ValueEnumerable`, but I&#39;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 &quot;as general as possible&quot;; 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.</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"></div></div></blockquote><div><br></div></span><div>Tony&#39;s &quot;no more specific than they need to&quot; language applies here. The way I see it is this:</div><div><br></div><div>* `Bool` is not an enum, but it could be usefully conformed to `ValueEnumerable`. Why should we prevent that?</div><div>* A type with two independently-switchable `Bool`s—say, `isMirrored` and `isFlipped`—could be usefully conformed to `ValueEnumerable`. Why should we prevent that?</div><div>* Having integer types conform to `ValueEnumerable` with `static let allValues = Self.min...Self.max` could be useful. Why should we prevent that?</div></div></div></blockquote><div><br></div><div>I&#39;d say you&#39;re looking at it the wrong way. We&#39;re not *preventing* anything. We&#39;re adding a feature, and the question is, why should we *add* more than is justified by the use case?</div><div><br></div><div>Is there a clamor for enumerating the two possible values of `Bool`? If so, is that not an argument instead to make `Bool` an enum and not a struct under the hood?</div><div>Is there a clamor for enumerating the possible values of a type with two independently switchable `Bool`s? If so, is that not an argument to make `Bool` a valid raw value type? (There is already a bug report to make tuples of raw value types valid raw value types themselves.)</div><div>Why is it useful for (fixed-width) integer types to conform to `ValueEnumerable`? What use cases, exactly, would that enable that are not possible now?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space"><div><div></div><div>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.</div><span class=""><br><blockquote type="cite"><div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">Along the lines of user ergonomics, I would advocate for as many enums as possible to conform without explicit opt-in. It&#39;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.</div></div></blockquote></span></div><div><br></div><div>But `RawRepresentable` *doesn&#39;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&#39;t actually think of a way to make opting in easier than conforming to a protocol and letting the complier synthesize the requirements.</div></div></blockquote><div><br></div><div>Yes, you&#39;re right that `RawRepresentable` conformance *doesn&#39;t* get automatically added in, but there exists special sugar which makes the end result indistinguishable. By this I mean that the user gets `RawRepresentable` conformance without ever writing `Foo : RawRepresentable` anywhere (and neither do they write `Foo : Bar` where `Bar` is in turn `RawRepresentable`).</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space"><div>(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&#39;t have this feature be opt-out without moving away from using a protocol.)</div></div></blockquote><div><br></div><div>This is, in fact, a perfect opportunity to bring up a question I&#39;ve been leaving implicit. Why not explore moving away from using a protocol? The proposed protocol has no syntactic requirements, and when constrained only the use case of enums, it has essentially no semantic requirements either. It seems that it&#39;s only because we&#39;ve committed to using a protocol that we&#39;ve opened up this exploration of what it means semantically to be `ValueEnumerable`, and how to generalize it to other types, and how to design the return type of the synthesized function, etc.</div><div><br></div><div>What if some attribute would simply make the metatype conform to `Sequence` (or, for that matter, `BidirectionalCollection`)?</div><div><br></div></div></div></div>