<div dir="ltr"><div class="gmail_extra"><div><div><div dir="ltr"><div>On Sat, Apr 16, 2016 at 5:20 AM, plx via swift-evolution <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span> wrote:<br></div></div></div></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><span><div><br></div></span><div><br></div><div>My 2c is that if this is to go in the standard library, it should be done “right”, which would be more like this version of it:</div><div><br></div><div>protocol ValueEnumerable {</div><span><div>  associatedtype ValueCollection : Collection where ValueCollection.Iterator.Element == Self</div></span><div>  static var allValues: ValueCollection</div><div>}</div><div><br></div><div>…and that this concept should simply *wait* for that feature to be available before going into the standard library. </div><div><br></div><div>The reason I say this is simply b/c it sounds like this proposal wants to be able to support more than simple enumerations, in which case having some flexibility in the representation seems appropriate. Consider e.g.:</div><div><br></div><div>  struct AxisPolicy3D&lt;Policy:protocol&lt;Equatable,ValueEnumerable&gt;&gt; {</div><div>    var x: Policy</div><div>    var y: Policy</div><div>    var z: Policy</div><div>  }</div><div><br></div><div>  extension AxisPolicy3D : ValueEnumerable {</div><div><br></div><div>    static let allValues: ValueCollection = product(Policy.allValues,Policy.allValues,Policy.allValues).lazy.map() { </div><div>        (x,y,z) </div><div>        in</div><div>        AxisPolicy3D(x: x, y: y, z: z)</div><div>    }</div><div><br></div><div>  }</div><div><br></div><div>…and similar, wherein the cost of *requiring* an array here could become rather large.</div><div><br></div><div>But I have a couple general concerns here:</div><div><br></div><div># Resiliency </div><div><br></div><div>My understanding is that the design for resiliency vis-a-vis enumerations is meant to allow enumerations to have cases added in future revisions (and perhaps also private cases? I didn’t follow resiliency closely). </div><div><br></div><div>If that’s right, and this protocol is supposed to go into the standard library, it might also need to address such issues. I have no help to offer and would love to be wrong about this point.</div></div></div></blockquote><div><br></div><div>Thank you for bringing this up; I hadn&#39;t thought about it. Indeed, the library evolution design document &lt;<a href="http://jrose-apple.github.io/swift-library-evolution/#enums" target="_blank">http://jrose-apple.github.io/swift-library-evolution/#enums</a>&gt; states that adding new cases, adding raw types, and reordering cases should be binary-compatible changes.</div><div><br></div><div>I hope someone who knows more about the resilience design can weigh in here. I&#39;ll CC Jordan Rose and John McCall, authors of that document, on this email.</div><div><div><br>I think you&#39;re right that the implications of requiring an array might be significant, if this array is exported as public API in a module which other binaries depend on. So I wonder if it might be possible to pursue a solution which <b>doesn&#39;t</b> export any additional public API in a module.</div><div><br></div><div>Recall that we&#39;d like to be able to add ValuesEnumerable support in an extension, both on Swift enums and on enums imported from Obj-C. Seems like you might <b>not</b> want those conformances to be exported, so that future changes in the type of allValues wouldn&#39;t have to break existing compiled binaries. (But currently, IIUC, extensions which add protocol conformances must be public.)</div><div><br></div><div>I&#39;m almost wondering whether we should be doing something like <b>#allValues(MyEnum)</b>, which uses # to indicate &quot;compiler magic&quot; (for now it would produce an Array&lt;MyEnum&gt;), gathering the available cases from the module at compile time. At some time in the future, when reflection is much more mature, perhaps this could be replaced with a standard library function.</div><div><br></div></div><div>---</div><div><br></div><div>This also prompted me to research Java&#39;s implementation a bit more. I&#39;m not a Java user, let alone expert, but here&#39;s what I found:</div><div><br></div><div>Class.getEnumConstants() returns the values <b>in source order</b>.  &lt;<a href="https://docs.oracle.com/javase/tutorial/reflect/special/enumMembers.html" target="_blank">https://docs.oracle.com/javase/tutorial/reflect/special/enumMembers.html</a>&gt; The page also says the following: </div><div><br></div><div><i>Note: For various reasons, including support for evolution of the enum type, the declaration order of enum constants is important. Class.getFields() and Class.getDeclaredFields() do not make any guarantee that the order of the returned values matches the order in the declaring source code. If ordering is required by an application, use Class.getEnumConstants().</i></div><div> </div><div>There&#39;s also a section on &quot;Evolution of Enums&quot; in this page about Binary Compatibility: &lt;<a href="https://docs.oracle.com/javase/specs/jls/se7/html/jls-13.html#jls-13.4.26" target="_blank">https://docs.oracle.com/javase/specs/jls/se7/html/jls-13.html#jls-13.4.26</a>&gt;  <i>&quot;Adding or reordering constants in an enum type will not break compatibility with pre-existing binaries.&quot;</i></div><div><br></div><div>Point being that getEnumConstants() always returns an array, it just might have different things in it depending on the version of the class you&#39;re interrogating.</div><div> </div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><div># Other Remarks</div><div><br></div><div>I see the `CaseEnumerable` discussion in the other discussion. It’s certainly related, but it’s something with enough independent utility I wouldn’t want it to get “lost” in this topic (especially since I think this topic is a great feature for the language, but one that may be awhile coming). </div></div></div></blockquote><div><br></div><div>CaseEnumerable was just an earlier name for Value(s)Enumerable. The stuff in the &quot;Future directions&quot; section remains speculative. I think we should keep the proposal focused if we want it to ever happen; improvements can come later.</div><div><br></div><div><br></div><div>Jacob</div></div></div></div>