<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 class="">On Dec 23, 2016, at 3:28 PM, David Sweeris via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Dec 23, 2016, at 2:02 PM, Xiaodi Wu <<a href="mailto:xiaodi.wu@gmail.com" class="">xiaodi.wu@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">I don't currently have a use for it, but I can certainly see how this might be useful to some people.<div class=""><br class=""></div><div class="">As a side note, though, it seems like the consensus is that the optimization shown in your specific example, which is provided by std::vector<bool> in C++, is now widely regarded as a poor design choice. See, for instance, <<a href="http://stackoverflow.com/questions/17794569/why-is-vectorbool-not-a-stl-container" class="">http://stackoverflow.com/questions/17794569/why-is-vectorbool-not-a-stl-container</a>>, <<a href="https://isocpp.org/blog/2012/11/on-vectorbool" class="">https://isocpp.org/blog/2012/11/on-vectorbool</a>>, and <<a href="http://www.gotw.ca/publications/N1211.pdf" class="">http://www.gotw.ca/publications/N1211.pdf</a>>.</div><div class=""><br class=""></div><div class="">It would be interesting to see if you can come up with a use case where the proposed feature is a clear win as opposed to just having a totally separate type that makes clear it's not quite the same thing under the hood (in your example, something like `BitArray`).</div></div></div></blockquote><br class=""></div><div class="">I'm starting to think my original motivation might’ve had something to do with normally needing storage for both some property <i class="">and</i> a T, but not needing (local) storage for said property if T conformed to a protocol which itself already required conforming types to have that property? Or maybe as a way to have the “bottom” variable in a hierarchy of wrapper types to break the “reference cycle” for some property? (Come to think of it, those could be the same thing)</div><div class=""><br class=""></div><div class="">That was (and is) an odd project... Anyway, it's been a while since I've thought about it. I'll try to find time today to poke through some old code and see if still have a copy of what I’d gotten stuck on.</div><div class=""><br class=""></div><div class="">And thanks for those links :-)</div></div></div></blockquote><br class=""></div><div>This isn’t what I’d been thinking of earlier, but what about Optionals? I seem to recall reading somewhere that an Optional<Unsafe*Pointer> took up the same amount of storage as the Unsafe*Pointer itself because the compiler could use Unsafe*Pointer's null-pointer value to represent the `.none` case. What if we extended that to any type that’s ExpressibleByNilLiteral & Equatable? I *think* we’d have to introduce the feature of “computed cases” to actually implement it without compiler magic (and getting rid of compiler magic for Optional<Unsafe*Pointer> would be half the point, in this instance):</div><br class=""><div class=""><div style="margin: 0px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">enum</span><span style="font-variant-ligatures: no-common-ligatures" class=""> Optional<T></span><span style="font-variant-ligatures: no-common-ligatures;" class=""> : </span><span style="font-variant-ligatures: no-common-ligatures; color: rgb(112, 61, 170);" class="">ExpressibleByNilLiteral</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> {...} </span><span style="font-variant-ligatures: no-common-ligatures; color: rgb(0, 132, 0);" class="">// Same as now</span></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="font-family: Menlo; margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">enum</span><span style="font-variant-ligatures: no-common-ligatures" class=""> Optional<T> : </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">ExpressibleByNilLiteral</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">where</span><span style="font-variant-ligatures: no-common-ligatures" class=""> T: ExpressibleByNilLiteral & Equatable {</span></div><div style="font-family: Menlo; margin: 0px; line-height: normal; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">case</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> some(</span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">T</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">) </span><span style="font-variant-ligatures: no-common-ligatures" class="">// Only one case, so storage-wise, nothing extra is needed</span></div><div style="font-family: Menlo; margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">init</span><span style="font-variant-ligatures: no-common-ligatures" class="">(</span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">_</span><span style="font-variant-ligatures: no-common-ligatures" class=""> value: </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">T</span><span style="font-variant-ligatures: no-common-ligatures" class="">) { </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">self</span><span style="font-variant-ligatures: no-common-ligatures" class=""> = .</span><span style="font-variant-ligatures: no-common-ligatures; color: #31595d" class="">some</span><span style="font-variant-ligatures: no-common-ligatures" class="">(value) }</span></div><div style="font-family: Menlo; margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">init</span><span style="font-variant-ligatures: no-common-ligatures" class="">(nilLiteral: ()) { </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">self</span><span style="font-variant-ligatures: no-common-ligatures" class=""> = .</span><span style="font-variant-ligatures: no-common-ligatures; color: #31595d" class="">some</span><span style="font-variant-ligatures: no-common-ligatures" class="">(<span style="color: rgb(187, 44, 162);" class="">nil</span> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">as</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">T</span><span style="font-variant-ligatures: no-common-ligatures" class="">) }</span></div><div style="font-family: Menlo; margin: 0px; line-height: normal; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span><span style="font-variant-ligatures: no-common-ligatures" class="">/* "var case `label`" declares a "computed case", a case that doesn't needs</span></div><div style="font-family: Menlo; margin: 0px; line-height: normal; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> * any extra bits to "store".</span></div><div style="font-family: Menlo; margin: 0px; line-height: normal; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> * In the return value, `.matches` tells the pattern matcher if there's a</span></div><div style="font-family: Menlo; margin: 0px; line-height: normal; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> * match, and `.associatedValue` carries any associated values. It probably</span></div><div style="font-family: Menlo; margin: 0px; line-height: normal; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> * shouldn't even exist in this example, since we're modeling `.none` rather</span></div><div style="font-family: Menlo; margin: 0px; line-height: normal; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> * than `.none(Void)`, but Swift doesn't currently allow for single-element</span></div><div style="font-family: Menlo; margin: 0px; line-height: normal; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> * tuples. In practice, all this means is that we'd need to consider `case</span></div><div style="font-family: Menlo; margin: 0px; line-height: normal; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> * label(Void)` to be the same as `case label`.</span></div><div style="font-family: Menlo; margin: 0px; line-height: normal; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> */</span></div><div style="font-family: Menlo; margin: 0px; line-height: normal;" class=""><span style="color: rgb(0, 132, 0); font-variant-ligatures: no-common-ligatures;" class=""> </span><span style="color: rgb(187, 44, 162); font-variant-ligatures: no-common-ligatures;" class="">var</span><span style="color: rgb(0, 132, 0); font-variant-ligatures: no-common-ligatures;" class=""> </span><span style="color: rgb(187, 44, 162); font-variant-ligatures: no-common-ligatures;" class="">case</span><span style="font-variant-ligatures: no-common-ligatures;" class=""><font color="#008400" class=""> </font>none<span style="font-variant-ligatures: no-common-ligatures;" class="">:</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> (matches: </span><span style="color: rgb(112, 61, 170); font-variant-ligatures: no-common-ligatures;" class="">Bool</span><span style="font-variant-ligatures: no-common-ligatures;" class="">, associatedValue: </span><span style="color: rgb(112, 61, 170); font-variant-ligatures: no-common-ligatures;" class="">Void</span><span style="font-variant-ligatures: no-common-ligatures;" class="">) {</span></span></div><div style="font-family: Menlo; margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">switch</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">self</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {</span></div><div style="font-family: Menlo; margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">case</span><span style="font-variant-ligatures: no-common-ligatures" class=""> .</span><span style="font-variant-ligatures: no-common-ligatures; color: #31595d" class="">some</span><span style="font-variant-ligatures: no-common-ligatures" class="">(let value): </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span><span style="font-variant-ligatures: no-common-ligatures" class=""> (value </span><span style="font-variant-ligatures: no-common-ligatures; color: #3d1d81" class="">== </span><span style="font-variant-ligatures: no-common-ligatures" class=""><span style="color: rgb(187, 44, 162); font-variant-ligatures: no-common-ligatures;" class="">nil</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> </span><span style="color: rgb(187, 44, 162); font-variant-ligatures: no-common-ligatures;" class="">as</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: rgb(79, 129, 135);" class="">T</span></span><span style="font-variant-ligatures: no-common-ligatures" class="">, ())</span></div><div style="font-family: Menlo; margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> }</span></div><div style="font-family: Menlo; margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> }</span></div><div style="font-family: Menlo; margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">}</span></div><div class=""><br class=""></div><div class="">- Dave Sweeris</div></div></div></div></body></html>