<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div dir="ltr" class=""><div class=""><div class="gmail_signature"><div dir="ltr" class=""><div class=""><div style="font-size:12.8px" class=""><div class=""><div dir="ltr" class=""><ul style="padding:0px 0px 0px 2em;margin-top:0px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px;margin-bottom:0px!important" class=""><li style="margin-left:15px" class=""><p style="margin-top:16px;margin-bottom:16px" class=""><br class="">Support for enum case&nbsp;<strong class="">names</strong>. It would be useful to get case names even for enums which have integer rawValues. This could be part of the existing reflection APIs, or it could take the form of derived implementations of StringLiteralConvertible/CustomStringConvertible.</p><div class=""><br class=""></div></li></ul></div></div></div></div></div></div></div></div></blockquote><div><br class=""></div>I’d love to see reflection move to an opt-in model, with a compiler flag enabling reflection for all types in a module, and a protocol to opt-in conditionally otherwise.</div><div><blockquote type="cite" class=""><div dir="ltr" class=""><div class=""><div class="gmail_signature"><div dir="ltr" class=""><div class=""><div style="font-size:12.8px" class=""><div class=""><div dir="ltr" class=""><ul style="padding:0px 0px 0px 2em;margin-top:0px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px;margin-bottom:0px!important" class=""><li style="margin-left:15px" class=""><p style="margin-top:16px;margin-bottom:16px" class="">Support for enums with associated values.</p><div class=""><br class=""></div></li></ul></div></div></div></div></div></div></div></div></blockquote><div><br class=""></div><div>This seems tricky to use statically in the general case, as you see below. Do you have any good examples in mind? It seems that case enumeration only really makes sense for types with a finite number of elements, and not when you have associated values.</div><div><br class=""></div><div>Perhaps it should only work if the associated values are themselves enums, and they can be enumerated recursively? But even that seems overkill, and something that people should implement themselves if they need it.</div><div><br class=""></div><blockquote type="cite" class=""><div dir="ltr" class=""><div class=""><div class="gmail_signature"><div dir="ltr" class=""><div class=""><div style="font-size:12.8px" class=""><div class=""><div dir="ltr" class=""><ul style="padding:0px 0px 0px 2em;margin-top:0px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px;margin-bottom:0px!important" class=""><li style="margin-left:15px" class=""><ul style="padding:0px 0px 0px 2em;margin-top:0px;margin-bottom:0px" class=""><li style="margin-left:15px" class=""><p style="margin-top:16px;margin-bottom:16px" class="">If Swift had anonymous sum types like&nbsp;<code class="" style="font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">A | B | C</code>, then&nbsp;<code class="" style="font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">E.cases</code>&nbsp;could vend elements of type&nbsp;<code class="" style="font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">A-&gt;E | B-&gt;E | C-&gt;E</code>.</p><div class=""><br class=""></div></li></ul></li></ul></div></div></div></div></div></div></div></div></blockquote><div><br class=""></div>As part of write reflection, it would make sense to expose constructor functions [Any -&gt; E?] that perform a dynamic type check, failing with nil.</div><div><br class=""></div><div>Imagine if you could reflect an enum of type T, and get an array of [EnumCase&lt;T&gt;]:</div><div><br class=""></div><div>enum EnumCase&lt;T&gt; {</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>// constructor makes a value: Payload -&gt; T</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>// projection tests a value, returning payload if its that case, or nil: T -&gt; Payload?</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>// type is the runtime type of the payload</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>case PayloadCase(name: String, constructor: Any -&gt; T, projection: T -&gt; Any?, type: Any.Type)</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>case EmptyCase(name: String, value: T)</div><div>}</div><div><br class=""></div><div>Then you can get representative values of all cases by mapping over this array, returning the ‘value’ element of an EmptyCase.</div><div><br class=""></div><div><br class=""><blockquote type="cite" class=""><div dir="ltr" class=""><div class=""><div class="gmail_signature"><div dir="ltr" class=""><div class=""><div style="font-size:12.8px" class=""><div class=""><div dir="ltr" class=""><ul style="padding:0px 0px 0px 2em;margin-top:0px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px;margin-bottom:0px!important" class=""><li style="margin-left:15px" class=""><ul style="padding:0px 0px 0px 2em;margin-top:0px;margin-bottom:0px" class=""><li style="margin-left:15px" class=""><div style="margin-bottom:16px" class=""><pre style="white-space:pre-wrap;overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;padding:16px;border-radius:3px;word-wrap:normal;background-color:rgb(247,247,247)" class=""><span style="color:rgb(167,29,93)" class="">enum</span> Expr { <span style="color:rgb(167,29,93)" class="">case</span> Apply(Expr, Expr), Tuple(Expr, Expr), Literal(<span style="color:rgb(0,134,179)" class="">Int</span>) }
<span style="color:rgb(167,29,93)" class="">extension</span> Value: CaseEnumerable {}

<span style="color:rgb(150,152,150)" class="">// This example is pretty contrived, but illustrates the functionality.</span>
<span style="color:rgb(167,29,93)" class="">let</span> fortyTwos <span style="color:rgb(167,29,93)" class="">=</span> Expr<span style="color:rgb(167,29,93)" class="">.</span>cases<span style="color:rgb(167,29,93)" class="">.</span><span style="color:rgb(0,134,179)" class="">map</span> {
   <span style="color:rgb(150,152,150)" class="">// $0 is of type `Int -&gt; Expr | (Expr, Expr) -&gt; Expr`</span>
   <span style="color:rgb(167,29,93)" class="">switch</span> $<span style="color:rgb(0,134,179)" class="">0</span> {
   <span style="color:rgb(167,29,93)" class="">case</span> <span style="color:rgb(167,29,93)" class="">let</span> lit <span style="color:rgb(167,29,93)" class="">as</span> <span style="color:rgb(0,134,179)" class="">Int</span> <span style="color:rgb(167,29,93)" class="">-&gt;</span> Expr:  <span style="color:rgb(150,152,150)" class="">// handles .Literal</span>
       <span style="color:rgb(167,29,93)" class="">return</span> lit(<span style="color:rgb(0,134,179)" class="">42</span>)
   <span style="color:rgb(167,29,93)" class="">case</span> <span style="color:rgb(167,29,93)" class="">let</span> bin <span style="color:rgb(167,29,93)" class="">as</span> (Expr, Expr) <span style="color:rgb(167,29,93)" class="">-&gt;</span> Expr:  <span style="color:rgb(150,152,150)" class="">// handles .Apply and .Tuple</span>
       <span style="color:rgb(167,29,93)" class="">return</span> bin(<span style="color:rgb(167,29,93)" class="">.</span>Literal(<span style="color:rgb(0,134,179)" class="">42</span>), <span style="color:rgb(167,29,93)" class="">.</span>Literal(<span style="color:rgb(0,134,179)" class="">42</span>))
   <span style="color:rgb(150,152,150)" class="">// all cases are covered</span>
   }
}</pre></div></li></ul></li></ul></div></div></div></div></div></div></div></div></blockquote><div><br class=""></div>I think in this example program, it would make more sense to define these data types:</div><div><br class=""></div><div>enum BinaryExprKind { cae Apply, Tuple }</div><div>enum Expr { case Binary(Kind, Expr, Expr), Literal(Int) }</div><div><br class=""></div><div>You can still enumerate the cases of&nbsp;BinaryExprKind dynamically, but destructuring Expr requires a switch.<br class=""><blockquote type="cite" class=""><div dir="ltr" class=""><div class=""><div class="gmail_signature"><div dir="ltr" class=""><div class=""><div style="font-size:12.8px" class=""><div class=""><div dir="ltr" class=""><ul style="padding:0px 0px 0px 2em;margin-top:0px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;line-height:25.6px;margin-bottom:0px!important" class=""><li style="margin-left:15px" class=""><p style="margin-top:16px;margin-bottom:16px" class="">Support for generic enums.</p><ul style="padding:0px 0px 0px 2em;margin-top:0px;margin-bottom:0px" class=""><li style="margin-left:15px" class=""><p style="margin-top:16px;margin-bottom:16px" class="">CaseEnumerable could be conditionally supported depending on the generic argument(s). A great example would be Optional:</p><div style="margin-bottom:16px" class=""><pre style="white-space:pre-wrap;overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;padding:16px;border-radius:3px;word-wrap:normal;background-color:rgb(247,247,247)" class=""><span style="color:rgb(167,29,93)" class="">enum</span> MyEnum: CaseEnumerable {}
<span style="color:rgb(167,29,93)" class="">extension</span> <span style="color:rgb(0,134,179)" class="">Optional</span>: CaseEnumerable <span style="color:rgb(167,29,93)" class="">where</span> Wrapped: CaseEnumerable {}

<span style="color:rgb(150,152,150)" class="">// Optional&lt;MyEnum&gt;.cases effectively contains `MyEnum.cases + [.None]`</span></pre></div></li></ul></li></ul></div></div></div></div></div></div></div>
</div>
_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></blockquote></div><br class=""></body></html>