<div dir="ltr"><div class="gmail_extra"><div><div class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div>On Wed, Jan 10, 2018 at 3:06 AM, Brent Royal-Gordon 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:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space"><div><blockquote type="cite"><span class=""><div>On Jan 9, 2018, at 10:26 PM, Xiaodi Wu via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br class="m_5053014394289224912Apple-interchange-newline"></span><span class=""><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">I continue to have concerns about this proposal, and I&#39;m gravely and very bitterly disappointed that the concerns have not even been acknowledged in the Alternatives section, which is in my view the minimum action that an author should take when points are raised during a pitch phase, even (and especially) when the author disagrees, along with a cogent write-up of why the proposed design is superior in the author&#39;s view to the alternative. In this case, the proposal authors write:</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"><br></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">  &quot;The community has not raised any solutions whose APIs differ significantly from this proposal, except for solutions which provide strictly more functionality.&quot;</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"><br></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">This is false, as I have offered a solution in the past whose API differs entirely from this proposal, and which provides strictly a subset of the functionality which goes to the core of the issue at stake.</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></span></blockquote><div><br></div><div>I can&#39;t speak for the other co-authors, but for my part, this was an oversight and I apologize for it. I think we should have discussed your `MyType.self` alternative.</div></div></div></blockquote><div><br></div><div>I echo Brent&#39;s sentiment — omissions were not intentionally disingenuous but the result of a slow proposal writing/revision process, and clearly my failure to adequately capture all of the mailing list discussion in the proposal &amp; alternatives even when it was updated in the days before the review began. In the event the proposal is returned for revision, we can revisit this to ensure all viewpoints are represented. Thanks, as always, for your detailed reply.</div><div><br></div><div>Jacob</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><br></div><div>I won&#39;t rehash the entire discussion in previous threads, but to summarize my objections:</div><div><br></div><div><div><span class="m_5053014394289224912Apple-tab-span" style="white-space:pre-wrap">        </span>1. `MyType.self` is harder to understand for someone who&#39;s never seen it than `MyType.allValues`. For instance, the expression `AccountStatus.allValues[0]` is completely self-explanatory, while `AccountStatus.self[0]` is more obscure and would require a trip to the documentation. (And since `self` here is a language keyword, not a real member, the most obvious route to the documentation is not available.) In my opinion, we should not prefer the `MyType.self` syntax.</div><div><br></div><div><span class="m_5053014394289224912Apple-tab-span" style="white-space:pre-wrap">        </span>2. Even if the community disagrees with me and thinks `MyType.self` is a better syntax than `MyType.allValues`, it is not better *enough* to outweigh the costs:</div><div><br></div><div><span class="m_5053014394289224912Apple-tab-span" style="white-space:pre-wrap">                </span>• The metatype solution provides no additional functionality; it is merely a matter of which syntax we choose to support, and how much effort this support requires.</div><div><br></div><div><span class="m_5053014394289224912Apple-tab-span" style="white-space:pre-wrap">                </span>• Conforming the metatype to `Collection` requires a lot of type system features we do not currently have. Currently, structural types cannot conform to protocols, and metatypes are a structural type. Metatypes also cannot have subscripts currently. Your proposed design has a lot of prerequisites. That is not in and of itself disqualifying, but it should be weighed against it.</div></div><div><br></div><div><span class="m_5053014394289224912Apple-tab-span" style="white-space:pre-wrap">                </span>• You suggest that we should add bits and pieces of &quot;`Collection` functionality&quot; incrementally as engineering resources become available. The problem is that the most valuable part of the &quot;`Collection` functionality&quot; is conformance to `Collection` or at least `Sequence`, not the existence of any particular members of `Collection`, and this is the part that would require the most engineering resources.</div><div><br></div><div><span class="m_5053014394289224912Apple-tab-span" style="white-space:pre-wrap">                </span>• A large part of the work we would do before supporting this conformance would be disposed of immediately once we could get it. For instance, all of the work to support having a metatype instead of a sequence in a `for-in` statement would be thrown away as soon as we could conform to `Sequence`. So this looks less like slowly building up pieces of the feature until we have all of them in place, and more like creating temporary hacks to emulate the feature until we have the time to do it right.</div><div><br></div><div><div><span class="m_5053014394289224912Apple-tab-span" style="white-space:pre-wrap">                </span>• While this feature is not a showstopper, it is a highly desirable convenience. The proposal documents the high demand for this feature, so I won&#39;t elaborate on this point further.</div></div><div><br></div><div><span class="m_5053014394289224912Apple-tab-span" style="white-space:pre-wrap">                </span>• Therefore, adopting this design would add a lot of engineering complexity before we could fully support a highly desirable feature, merely to get a syntax that we *might* prefer.</div><div><br></div><div>To summarize the summary: The primary advantage of `MyType.self` is that it&#39;s elegant. To get that elegance, we must trade away getting a fully-functional implementation sooner, spending a lot of engineering resources (much of which would be wasted in the end), and—most crucially in my opinion—clarity at the point of use. It&#39;s not worth it.</div><span class=""><div><br></div><blockquote type="cite"><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">Earlier in this thread (or was it in the companion one?), another community member suggested that if `allValues` were to conform to `Sequence` instead of `Collection`, then even types that have an infinite number of possible values could conform to `ValueEnumerable`. Here&#39;s the rub: the definition of a type, or at least one of them, _is_ precisely the set of all possible values of a variable. If unconstrained by finiteness, then *all types* would meet the semantic requirements of `ValueEnumerable`.</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></blockquote><div><br></div></span><div>Not quite. There are types whose valid values are unknowable; for instance, a type representing &quot;the ID of a record on the server&quot; cannot know which IDs actually exist on the server, merely which ones *could* exist, and so an implementation of `allValues` would return invalid instances.</div><div><br></div><div>But that&#39;s beside the point. What I think the &quot;`allValues` should be allowed to be infinite&quot; suggestion misses is that one of `ValueEnumerable`&#39;s semantics is that it&#39;s not only theoretically *possible* to enumerate all the values, but actually *reasonable* to do so. This is more slippery and subjective than most protocol semantics, but I don&#39;t think that should disqualify it. There are plenty of places in the standard library where we make judgment calls like this. For instance, the decision that `Optional` should not conform to `Collection` is a similar judgment call: `Optional` could easily meet all of the formal requirements of a `Collection`, but we chose not to do it because we decided it didn&#39;t make *subjective* sense.</div><div><br></div><div>Some simple enums could not be reasonably conformed to `ValueEnumerable`; for instance, there&#39;s little sense in conforming an `Error` enum, because you&#39;re unlikely to need to discover all the possible errors expressed by a type at runtime. Some non-simple enums could be reasonably conformed to `ValueEnumerable`; `Bool` is an obvious example.</div><div><br></div><div>Some types, of course, fall into a gray area. `Int8` is fairly reasonable, but larger integer types get increasingly unreasonable until, by `Int64`, we reach types that would take decades to enumerate. Where the line should be drawn is a matter of opinion. (My opinion, to be clear, is that we shouldn&#39;t conform any of them; if someone really wants to do it, they can add a retroactive conformance.)</div><span class=""><div><br></div><blockquote type="cite"><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">As proposed, &quot;`ValueEnumerable`...indicate[<wbr>s] that a type has a finite, enumerable set of values&quot;; now, we have the constraint that the type merely must have an upper bound in terms of memory referenced. Brent just wrote that he might later propose to extend `ValueEnumerable` to `Bool` and `Optional`, but theoretically and practically speaking it appears that it can correctly be extended to any type in the standard library that is not a `Sequence`, and with minimal effort even `Collection` types of fixed size (e.g., CollectionOfOne&lt;T&gt; with the right constraints as to the generic type T).</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></blockquote><div><br></div></span><div><div>Sure, but theoretically speaking, we could synthesize a `Comparable` implementation for all classes which compared them by address. This implementation would be totally correct, would fulfill all of the requirements of the protocol it was conforming to, and would usually be meaningless. So we don&#39;t.</div><div><br></div><div>The fact that some types could be given a useless conformance to a protocol does not imply that the protocol shouldn&#39;t exist.</div></div><span class=""><br><blockquote type="cite"><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">First, &quot;ValueEnumerable&quot;-ness is neither universal to all enums (as those with associated types, indirect cases (think of all those tutorials about linked lists implemented as Swift enums), etc., are clearly not enumerable) nor unique as a property of enums,</div></blockquote><div><br></div></span><div>It&#39;s absolutely true that not all enums should be enumerable, and also true that many non-enums should be enumerable. That&#39;s precisely why the protocol is not `CaseEnumerable` and the property is not `allCases`.</div><span class=""><br><blockquote type="cite"><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">yet this proposal first makes a large generalization of the proposed protocol&#39;s semantics when the stated motivation is only about enums,</div></blockquote><div><br></div></span><div>Do you disagree that there are many types which are not enums, but which—like the enums we are trying to address with this proposal—it is also reasonable to want to retrieve all values of? Or do you think we have missed important aspects of these types by not deeply analyzing them? Or are you simply criticizing how this part of the proposal was drafted, despite believing that its conclusion is correct?</div><span class=""><br><blockquote type="cite"><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">then proceeds only to implement protocol conformance for enums.</div></blockquote><div><br></div></span>I think it&#39;s more accurate to say that it &quot;only synthesizes a default implementation for simple enums&quot;. This is for three reasons:</div><div><br></div><div><span class="m_5053014394289224912Apple-tab-span" style="white-space:pre-wrap">        </span>1. Simple enums will probably be the most common conforming types, even if they aren&#39;t the only ones.</div><div><br></div><div><span class="m_5053014394289224912Apple-tab-span" style="white-space:pre-wrap">        </span>2. We can very easily synthesize an implementation which uses private APIs to return an `Int`-indexed and zero-based `RandomAccessCollection`, is highly optimized, and is forward-compatible. That is, for this subset of types and no others, we can implement a no-compromises, ideal implementation using special knowledge.</div><div><br></div><div><span class="m_5053014394289224912Apple-tab-span" style="white-space:pre-wrap">        </span>3. We are only confident that we know enough about the type to synthesize its implementation when it&#39;s a simple enum.</div><div><div><br></div><div>More on that last point: Enums explicitly list all of the valid values in the source code. By contrast, a struct definition often permits values which are not actually valid because Swift&#39;s type system is not rich enough to conveniently express the constraints on their properties. For example, in these types:</div><div><br></div><div><span class="m_5053014394289224912Apple-tab-span" style="white-space:pre-wrap">        </span>struct PlayingCard: ValueEnumerable {</div><div><span class="m_5053014394289224912Apple-tab-span" style="white-space:pre-wrap">                </span>enum Suit: ValueEnumerable {</div><div><span class="m_5053014394289224912Apple-tab-span" style="white-space:pre-wrap">                        </span>case hearts, spades, diamonds, clubs</div><div><span class="m_5053014394289224912Apple-tab-span" style="white-space:pre-wrap">                </span>}</div><div><span class="m_5053014394289224912Apple-tab-span" style="white-space:pre-wrap">                </span></div><div><span class="m_5053014394289224912Apple-tab-span" style="white-space:pre-wrap">                </span>var suit: Suit</div><div><span class="m_5053014394289224912Apple-tab-span" style="white-space:pre-wrap">                </span>var rank: Int</div><div><span class="m_5053014394289224912Apple-tab-span" style="white-space:pre-wrap">        </span>}</div><div><br></div><div>The compiler can correctly synthesize `PlayingCard.Suit.allValues` because all of its constraints are specified in code. By contrast, the compiler cannot know that `rank` must be between 1 and 13, so if it tried to synthesize `PlayingCard.allValues`, it would contain invalid values.</div><div><br></div><div>These limitations are quite common in the types of code synthesis we&#39;ve introduced so far. For example, we only synthesize an `Equatable` conformance if all the types involved are themselves `Equatable`; that&#39;s not because `Equatable` is only applicable to those types, it&#39;s just that we can&#39;t be reasonably sure of the desired semantics. The limitation of `ValueEnumerable` synthesis to simple enums is similar.</div><span class=""><div><br></div><blockquote type="cite"><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">Second, the collection of all values is properly just the type and not a property of the type, for the reasons outlined above.</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></blockquote><div><br></div></span><div>Okay, let&#39;s say that&#39;s true. Is that the only or best way to express it?</div><span class=""><br><blockquote type="cite"><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">So far, the justification I have heard for ignoring this objection is that (a) lots of people want the specific use case of knowing all the cases of an enum; and (b) a complete design which makes metatypes conform to `Collection` is not feasible for Swift 5. But that, in my view, cannot justify the _permanent_ inclusion (with ABI stability) of a protocol whose semantics apply to all non-`Sequence` types, littering the standard library and untold many other libraries with this conformance for the sake of having something done for Swift 5.</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></blockquote><div><blockquote type="cite"><br></blockquote></div><blockquote type="cite"><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">My suggestion was, and is: if the motivation is to enumerate all the cases of an enum, deliver the best possible design for the specifically motivated use case rather than trying to deliver the most easy-to-implement design for the most general use case. In other words, give properly conformed enums (e.g. `enum MyEnum : Enumerable`--and I do suggest shortening the name, since what&#39;s enumerable is &quot;the set of all values&quot; == &quot;the type&quot;) the synthesized ability to have all cases enumerated by iterating over the metatype: `for case in MyEnum.self { ... }`. Add as much other `Collection` functionality as can be implemented in the Swift 5 timeframe, starting with the most pressing based on the motivating use case. Then deliver more and more of the best possible design with each version of Swift as engineering resources permit.</div></blockquote><br></span></div><div>There is nothing wrong with the proposed design. It&#39;s a good design, and depending on one&#39;s priorities, it&#39;s arguably the *best* design. That it&#39;s feasible to deploy today is just icing on the cake.</div><span class="HOEnZb"><font color="#888888"><br><div>
<span class="m_5053014394289224912Apple-style-span" style="border-collapse:separate;font-variant-ligatures:normal;font-variant-east-asian:normal;line-height:normal;border-spacing:0px"><div><div style="font-size:12px">-- </div><div style="font-size:12px">Brent Royal-Gordon</div><div style="font-size:12px">Architechies</div></div></span>

</div>
<br></font></span></div><br>______________________________<wbr>_________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br>
<br></blockquote></div><br></div></div>