<div dir="ltr"><div class="gmail_default" style="font-family:&#39;trebuchet ms&#39;,sans-serif"><span style="font-family:arial,sans-serif;font-size:12.8px">Jiannan, I agree there is an use for union types, I&#39;m just not really fond of the syntax (I&#39;d really prefer something like &#39;union&lt;...&gt;&#39;) and with using it for optionals. To enable this syntax for optionals, None would have to be a valid type of the language and that would enable one to create the following constructions:</span><br></div><div class="gmail_default" style="font-family:&#39;trebuchet ms&#39;,sans-serif"><span style="font-family:arial,sans-serif;font-size:12.8px"><br></span></div><div class="gmail_default" style="font-family:&#39;trebuchet ms&#39;,sans-serif"><span style="font-family:arial,sans-serif;font-size:12.8px">    func something(value: None) -&gt; None { ... }</span></div><div class="gmail_default" style="font-family:&#39;trebuchet ms&#39;,sans-serif"><span style="font-family:arial,sans-serif;font-size:12.8px"><br></span></div><div class="gmail_default" style="font-family:&#39;trebuchet ms&#39;,sans-serif"><span style="font-family:arial,sans-serif;font-size:12.8px">It wouldn&#39;t be essentially wrong but unnecessary since nil would be the only possible value of the type None. And I don&#39;t really see any need to change the way optionals are implemented to support unions. And we could still have optional unions using either syntax with existing optional syntax (which is very clear to me):</span></div><div class="gmail_default" style="font-family:&#39;trebuchet ms&#39;,sans-serif"><span style="font-family:arial,sans-serif;font-size:12.8px"><br></span></div><div class="gmail_default" style="font-family:&#39;trebuchet ms&#39;,sans-serif"><span style="font-family:arial,sans-serif;font-size:12.8px">    func something(value: (A | B | C)?) { ... }</span></div><div class="gmail_default" style="font-family:&#39;trebuchet ms&#39;,sans-serif"><span style="font-family:arial,sans-serif;font-size:12.8px"><br></span></div><div class="gmail_default" style="font-family:&#39;trebuchet ms&#39;,sans-serif"><span style="font-family:arial,sans-serif;font-size:12.8px">or</span></div><div class="gmail_default" style="font-family:&#39;trebuchet ms&#39;,sans-serif"><br></div><div class="gmail_default"><span style="font-size:12.8px">    func something(value: union&lt;A, B, C&gt;?) { ... }</span></div><div class="gmail_default" style="font-family:&#39;trebuchet ms&#39;,sans-serif"><span style="font-family:arial,sans-serif;font-size:12.8px"><br></span></div><div class="gmail_default">Just as I said before, I don&#39;t really think unions are necessary (did you mean overloading?) but I don&#39;t oppose them. I just don&#39;t think we need to change the way a feature already works to justify the addition of a new feature.</div><div class="gmail_default"><br></div></div><div class="gmail_extra"><br clear="all"><div><div class="gmail_signature"><div dir="ltr"><div><div dir="ltr"><font face="trebuchet ms, sans-serif">- Leonardo</font></div></div></div></div></div>
<br><div class="gmail_quote">On 16 May 2016 at 08:26, Cao Jiannan 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><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word">Union is far better then generic enum/protocol solution.<div><div>        * It can extend the original enum and make it powerful.</div><div><span style="white-space:pre-wrap">                </span></div><div><span style="font-family:&#39;Fira Code&#39;;font-size:11px;color:rgb(4,51,255)">enum</span><span style="font-family:&#39;Fira Code&#39;;font-size:11px"> ResultDataType {</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;"><span>    </span><span style="color:rgb(4,51,255)">case</span><span> Music</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;"><span>    </span><span style="color:rgb(4,51,255)">case</span><span> Video</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;"><span>    </span><span style="color:rgb(4,51,255)">case</span><span> File</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;"><span>}</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;;min-height:13px"><span></span><br></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;"><span style="color:rgb(4,51,255)">enum</span><span> FailureType {</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;"><span>    </span><span style="color:rgb(4,51,255)">case</span><span> HTTP404</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;"><span>    </span><span style="color:rgb(4,51,255)">case</span><span> HTTP502</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;"><span>}</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;;min-height:13px"><span></span><br></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;"><span style="color:rgb(4,51,255)">enum</span><span> FailureTypev2 {</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;"><span>    </span><span style="color:rgb(4,51,255)">case</span><span> HTTP451</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;"><span>}</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;"><span><br></span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;"><div style="margin:0px;line-height:normal;color:rgb(52,149,175)"><span style="color:rgb(4,51,255)">typealias</span><span style="color:rgb(0,0,0)"> Result = (</span><span>ResultDataType |</span><span style="color:rgb(0,0,0)"> </span><span>FailureType |</span><span style="color:rgb(0,0,0)"> </span><span>FailureTypev2</span><span style="color:rgb(0,0,0)">)</span></div><div style="margin:0px;line-height:normal;color:rgb(52,149,175)"><span style="color:rgb(0,0,0)"><br></span></div></div><div><span style="white-space:pre-wrap">        </span>* It keeps the code clear and does not need developer to announce some unnecessary protocols or enums.</div><div><span style="white-space:pre-wrap">                </span>like UnionOf3&lt;T,U,V&gt; or ProtocolForABC</div><div><br></div><div><div>        * It is easy to wrap original value into an union type.</div><div><span style="white-space:pre-wrap">                </span><span style="font-family:&#39;Fira Code&#39;;font-size:11px;color:rgb(4,51,255)">let</span><span style="font-family:&#39;Fira Code&#39;;font-size:11px"> a = </span><span style="font-family:&#39;Fira Code&#39;;font-size:11px;color:rgb(52,149,175)">A</span><span style="font-family:&#39;Fira Code&#39;;font-size:11px">()</span></div><div style="font-family:&#39;Fira Code&#39;;font-size:11px;margin:0px;line-height:normal"><span><span style="color:rgb(4,51,255)"><span style="white-space:pre-wrap">        </span>let</span> union: (A|B|C) = </span><span style="color:rgb(52,149,175)">a </span><span style="color:rgb(0,143,0)">// Automatically wrap.</span></div></div><div><br></div><div><div><span style="white-space:pre-wrap">        </span>* Compiler might search their common properties, and methods, then mark them as a member of the union type.</div><div><span style="white-space:pre-wrap">                </span><span style="font-family:&#39;Fira Code&#39;;font-size:11px">print(value.someCommonProperty) </span><span style="font-family:&#39;Fira Code&#39;;font-size:11px;color:rgb(0,143,0)">// Compiler will know their common properties automatically.</span></div></div><div><span style="font-family:&#39;Fira Code&#39;;font-size:11px;color:rgb(0,143,0)"><br></span></div><div><span style="font-family:&#39;Fira Code&#39;;font-size:11px;color:rgb(0,143,0)"><br></span></div><div><span style="font-family:&#39;Fira Code&#39;;font-size:11px;color:rgb(0,143,0)"><div style="color:rgb(0,0,0);font-family:Helvetica;font-size:12px"><span style="white-space:pre-wrap">        </span>* Compiler know the union type exactly composed with which types, better than only know which protocol.</div><div style="color:rgb(0,0,0);font-family:Helvetica;font-size:12px"><span style="white-space:pre-wrap">                </span><span style="font-family:&#39;Fira Code&#39;;font-size:11px;color:rgb(4,51,255)">func</span><span style="font-family:&#39;Fira Code&#39;;font-size:11px"> input(value: </span><span style="font-family:&#39;Fira Code&#39;;font-size:11px;color:rgb(52,149,175)">ProtocolForABC</span><span style="font-family:&#39;Fira Code&#39;;font-size:11px">) {</span></div></span><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;"><span><div style="margin:0px;line-height:normal"><span><span style="white-space:pre-wrap">                </span></span><span style="color:rgb(4,51,255)">if</span><span> value </span><span style="color:rgb(4,51,255)">is</span><span> </span><span style="color:rgb(52,149,175)">A</span><span> {</span></div></span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;;min-height:13px"><span>        </span><br></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;"><span>    <span style="white-space:pre-wrap">                </span>} </span><span style="color:rgb(4,51,255)">else</span><span> </span><span style="color:rgb(4,51,255)">if</span><span> value </span><span style="color:rgb(4,51,255)">is</span><span> </span><span style="color:rgb(52,149,175)">B</span><span> {</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;;min-height:13px"><span>        </span><br></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;"><span>    <span style="white-space:pre-wrap">                </span>} </span><span style="color:rgb(4,51,255)">else</span><span> </span><span style="color:rgb(4,51,255)">if</span><span> value </span><span style="color:rgb(4,51,255)">is</span><span> </span><span style="color:rgb(52,149,175)">C</span><span> {</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;;min-height:13px"><span>        </span><br></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;"><span>    <span style="white-space:pre-wrap">                </span>} </span><span style="color:rgb(4,51,255)">else</span><span> {</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;;color:rgb(0,143,0)"><span>        <span style="white-space:pre-wrap">                </span></span><span>// There are other cases? Compiler doesn&#39;t know</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;"><span>    <span style="white-space:pre-wrap">                </span>}</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;"><span><span style="white-space:pre-wrap">        </span>}</span></div></div><div><br></div><div>        * Original types and union types can have a rational relationship between each other. </div><div>               Original type is a sub-type of union types contain it.</div><div><div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;"><span><span style="color:rgb(4,51,255)"><br></span></span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;"><span><span style="color:rgb(4,51,255)"><span style="white-space:pre-wrap">        </span>var</span> fn0: <span style="color:rgb(52,149,175)">A</span>-&gt;<span style="color:rgb(52,149,175)">Void</span> = {<span style="color:rgb(52,149,175)">print</span>(v0)}</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;"><span><span style="color:rgb(4,51,255)"><span style="white-space:pre-wrap">        </span>var</span> fn1<span>: <font color="#3495af">(A|B)</font></span>-&gt;<span style="color:rgb(52,149,175)">Void</span> = {<span style="color:rgb(52,149,175)">print</span>(v0)}</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;"><br></div></div><div style="margin:0px;line-height:normal"><span style="font-family:&#39;Fira Code&#39;;font-size:11px"><span style="white-space:pre-wrap">        </span>fn0 = fn1 </span><span style="font-family:&#39;Fira Code&#39;;font-size:11px;color:rgb(0,143,0)">// Original Type and Union Type has a sub-typing relationship, OK</span></div><div style="font-family:&#39;Fira Code&#39;;font-size:11px;margin:0px;line-height:normal"><span><br></span></div><div style="font-family:&#39;Fira Code&#39;;font-size:11px;margin:0px;line-height:normal"><span><span style="color:rgb(4,51,255)"><span style="white-space:pre-wrap">        </span>var</span> fn2: <span style="color:rgb(52,149,175)">(A|B|C)</span>-&gt;<span style="color:rgb(52,149,175)">Void</span> = {<span style="color:rgb(52,149,175)">print</span>($0)}</span></div><div style="font-family:&#39;Fira Code&#39;;font-size:11px;margin:0px;line-height:normal"><span><br></span></div><div style="font-family:&#39;Fira Code&#39;;font-size:11px;margin:0px;line-height:normal"><span style="white-space:pre-wrap">        </span>fn0 = fn2 <span style="color:rgb(0,143,0)">// OK</span></div><div><span><div style="margin:0px;font-size:11px;line-height:normal;font-family:&#39;Fira Code&#39;"><span><span style="white-space:pre-wrap">        </span>fn1 = fn2 <span style="color:rgb(0,143,0)">// OK</span></span></div></span></div></div><div><br></div><div><br></div><div>        * It is also easy to compare with value of original type.</div><div><span style="white-space:pre-wrap">                </span><span style="font-family:&#39;Fira Code&#39;;font-size:11px">union == </span><span style="color:rgb(52,149,175);font-family:&#39;Fira Code&#39;;font-size:11px">a</span><span style="font-family:&#39;Fira Code&#39;;font-size:11px"> </span><span style="color:rgb(0,143,0);font-family:&#39;Fira Code&#39;;font-size:11px">// Can be compared, Yes for most cases.</span></div><div><br></div><div><span style="white-space:pre-wrap">        </span>* And the most important part, <b>It can replace Optional&lt;T&gt;.</b></div><div><b><span style="white-space:pre-wrap">                </span></b><span style="font-family:&#39;Fira Code&#39;;font-size:11px;color:rgb(4,51,255)">let</span><span style="font-family:&#39;Fira Code&#39;;font-size:11px"> string: String?</span></div><div><span style="font-family:&#39;Fira Code&#39;;font-size:11px"><span style="white-space:pre-wrap">        </span>is same to </span></div><div><b><span style="white-space:pre-wrap">                </span></b><span style="font-family:&#39;Fira Code&#39;;font-size:11px;color:rgb(4,51,255)">let</span><span style="font-family:&#39;Fira Code&#39;;font-size:11px"> string: (String | None)  instead of </span><span style="font-family:&#39;Fira Code&#39;;font-size:11px;color:rgb(4,51,255)">let</span><span style="font-family:&#39;Fira Code&#39;;font-size:11px"> string: Optional&lt;String&gt;</span></div><div><span style="white-space:pre-wrap">                </span></div><div><br></div><div>I really think the union type is a good supplement for Swift. Make the language rational.</div><div>And the It is also really good for Reactive Programming.           </div><div><br></div><div>- Jiannan  </div><div><div><div><div><br><blockquote type="cite"><div>下面是被转发的邮件:</div><br><div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px"><span style="font-family:-webkit-system-font,Helvetica Neue,Helvetica,sans-serif;color:rgba(0,0,0,1.0)"><b>发件人: </b></span><span style="font-family:-webkit-system-font,Helvetica Neue,Helvetica,sans-serif">Haravikk &lt;<a href="mailto:swift-evolution@haravikk.me" target="_blank">swift-evolution@haravikk.me</a>&gt;<br></span></div><div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px"><span style="font-family:-webkit-system-font,Helvetica Neue,Helvetica,sans-serif;color:rgba(0,0,0,1.0)"><b>主题: </b></span><span style="font-family:-webkit-system-font,Helvetica Neue,Helvetica,sans-serif"><b>回复: [swift-evolution] Union instead of Optional</b><br></span></div><div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px"><span style="font-family:-webkit-system-font,Helvetica Neue,Helvetica,sans-serif;color:rgba(0,0,0,1.0)"><b>日期: </b></span><span style="font-family:-webkit-system-font,Helvetica Neue,Helvetica,sans-serif">2016年5月16日 GMT+8 18:35:25<br></span></div><div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px"><span style="font-family:-webkit-system-font,Helvetica Neue,Helvetica,sans-serif;color:rgba(0,0,0,1.0)"><b>收件人: </b></span><span style="font-family:-webkit-system-font,Helvetica Neue,Helvetica,sans-serif">Austin Zheng &lt;<a href="mailto:austinzheng@gmail.com" target="_blank">austinzheng@gmail.com</a>&gt;<br></span></div><div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px"><span style="font-family:-webkit-system-font,Helvetica Neue,Helvetica,sans-serif;color:rgba(0,0,0,1.0)"><b>抄送: </b></span><span style="font-family:-webkit-system-font,Helvetica Neue,Helvetica,sans-serif">Cao Jiannan &lt;<a href="mailto:frogcjn@163.com" target="_blank">frogcjn@163.com</a>&gt;, Adrian Zubarev via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;<br></span></div><br><div><div><br><blockquote type="cite">On 16 May 2016, at 11:17, Austin Zheng via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:<br><br>If A, B, and C are not related via protocol or class inheritance, then there is almost nothing you can do with value. Otherwise you still need to test against the concrete type using a case statement or a if-else ladder.<br></blockquote><br>I think that a case statement or similar syntax will still be needed, and the case names would just be the types themselves. This would work best with support for type-narrowing, for example:<br><br><span style="white-space:pre-wrap">        </span>func someMethod(value:(A|B|C)) {<br><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span>switch (value) {<br><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span>case .A:<br><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span>value.someMethodForTypeA()<br><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span>case .B:<br><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span>value.someMethodForTypeB()<br><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span>case .C:<br><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span>value.someMethodForTypeC()<br><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span>}<br><span style="white-space:pre-wrap">        </span>}<br><br>A union should really just be though of as a lightweight, restricted form of enum that can be declared in a quick ad-hoc fashion, similar to how tuples are a simpler form of struct.<br><br>I’m generally a +1 for the feature, but I’d be interested to hear about how well equipped the compiler is for optimising something like this. In most cases an Optional covers what I need, and in more complex cases I’d probably declare overloads for each type (i.e- someMethod(value:A), someMethod(value:B) etc.); unions could make the latter case simpler, but will the compiler produce the same code behind the scenes, i.e- by isolating what’s unique to each type?</div></div></blockquote></div><br></div></div></div></div></div><br>_______________________________________________<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/mailman/listinfo/swift-evolution</a><br>
<br></blockquote></div><br></div>