<div dir="ltr">I&#39;m not sure what your objections actually are, but my responses are inline.<br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, May 18, 2016 at 1:57 PM, Adrian Zubarev 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"><div style="font-family:Helvetica,Arial;font-size:13px;color:rgba(0,0,0,1.0);margin:0px;line-height:auto"><span class=""><blockquote type="cite"><div style="word-wrap:break-word"><blockquote type="cite"><div><div style="margin:0px">So without any initial constraints how would one use this generic function??</div><div style="margin:0px"><br></div><div style="margin:0px">extension UIButton: ProtocolA {}</div><div style="margin:0px"><br></div><div style="margin:0px">let button = UIButton()</div><div style="margin:0px">let shadowedButton: ProtocolA = UIButton()</div><div style="margin:0px"><br></div><div style="margin:0px">// creates a set of a least one element if the generic type could be inferred</div><div style="margin:0px">func unionIfPossible&lt;T, U&gt;(_ a: T, _ b: U) -&gt; Set&lt;Any&lt;T, U&gt;&gt;? { /* merge somehow if possible */ }</div></div></blockquote><div><br></div><div>You would not be able to form Any&lt;T, U&gt; here because T and U are generic arguments unknown.  We don’t accept those, only `class`, specific classes, and specific protocols (and recursively, other Any).</div></div></blockquote><div style="font-family:Helvetica,Arial;font-size:13px;color:rgba(0,0,0,1.0);margin:0px;line-height:auto"><br></div></span><div style="font-family:Helvetica,Arial;font-size:13px;color:rgba(0,0,0,1.0);margin:0px;line-height:auto">Why would Any&lt;…&gt; does not work with the generic system here? To me it makes no sense, I as a developer would assume I can use a generic Type anywhere a type can be used (protocols and their associated types are a special case).</div></div></div></blockquote><div><br></div><div>Because what existentials are trying to model and what generic type parameters are trying to model are two different things. You already cannot use arbitrary types within a Any&lt;&gt; existential as the proposal stands.</div><div><br></div><div>This doesn&#39;t currently work in Swift, and it shouldn&#39;t: &quot;func foo&lt;A, B&gt;() -&gt; protocol&lt;A, B&gt;&quot;. There is no useful way to generically compose instances of two protocol types at runtime to form an instance of a type that conforms to both protocols, like there is a way to compose instances of two types to form a tuple containing those types. Therefore, writing a generic function to do this makes no sense.</div><div><br></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"><div style="font-family:Helvetica,Arial;font-size:13px;color:rgba(0,0,0,1.0);margin:0px;line-height:auto"><div style="font-family:Helvetica,Arial;font-size:13px;color:rgba(0,0,0,1.0);margin:0px;line-height:auto"><br></div><div style="font-family:Helvetica,Arial;font-size:13px;color:rgba(0,0,0,1.0);margin:0px;line-height:auto">I would assume that:</div><div style="font-family:Helvetica,Arial;font-size:13px;color:rgba(0,0,0,1.0);margin:0px;line-height:auto"><br></div><div style="font-family:Helvetica,Arial;font-size:13px;color:rgba(0,0,0,1.0);margin:0px;line-height:auto">func foo&lt;T: UIView&gt;(value: Any&lt;T, SomeProtocol&gt;)</div><div style="font-family:Helvetica,Arial;font-size:13px;color:rgba(0,0,0,1.0);margin:0px;line-height:auto"><br></div><div style="font-family:Helvetica,Arial;font-size:13px;color:rgba(0,0,0,1.0);margin:0px;line-height:auto">should be equal to (without the need of generics):</div><div style="font-family:Helvetica,Arial;font-size:13px;color:rgba(0,0,0,1.0);margin:0px;line-height:auto"><br></div><div style="font-family:Helvetica,Arial;font-size:13px;color:rgba(0,0,0,1.0);margin:0px;line-height:auto">func foo(value: Any&lt;UIView, SomeProtocol&gt;)</div><span class=""><br><div><blockquote type="cite" style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div style="word-wrap:break-word"><blockquote type="cite"><div><div style="margin:0px"><br>// this should be valid because the compiler will assume Any&lt;UIView, ProtocolA&gt; where T == UIView and U == ProtocolA</div><div style="margin:0px">let merged_1: Set&lt;Any&lt;UIView, ProtocolA&gt;&gt; = unionIfPossible( /* UIView subtype */ button, /* ProtocolA */ shadowedButton) </div><div style="margin:0px"><br></div><div style="margin:0px"><div style="margin:0px">// this won’t be possible because of the restriction</div><div style="margin:0px">let merged_2: Set&lt;Any&lt;UIView, ProtocolA&gt;&gt; = unionIfPossible(shadowedButton, button) </div><div style="margin:0px"><br></div><div style="margin:0px">Any&lt;UIView, ProtocolA&gt; != Any&lt;ProtocolA, UIView&gt; isn’t right. Sure it may feel right for readability but the types should be equal.</div><div style="margin:0px"><br></div><div style="margin:0px">&quot;Can be any class type that is a UIView or a subclass of UIView, that also conforms to ProtocolA.“ == &quot;Type that conforms to ProtocolA and that is a UIView or a subclass of UIView.“</div><div style="margin:0px"><br></div><div style="margin:0px">This is also a nesting problem where you will be forced to choose the right place inside the angle brackets where to add a nested `Any&lt;…&gt;`.</div><div style="margin:0px"><br></div><div style="margin:0px">class A: ClassB, ProtocolA {}</div><div style="margin:0px"><br></div><div style="margin:0px">Any&lt;A, Any&lt;ClassB, ProtocolA&gt;&gt; == A != Any&lt;Any&lt;ClassB, ProtocolA&gt;, A&gt; == Any&lt;ClassB, ProtocolA, A&gt; which should be reorder by the compiler and inferred as A</div></div></div></blockquote><div><br></div><div>`Any&lt;Any&lt;ClassB, ProtocolA&gt;, A&gt;` is not allowed because if a class is provided it must come first.</div><div><br></div><div>`<span>Any&lt;ClassB, ProtocolA, A&gt;` is not allowed because it contains more than one class.</span></div></div></blockquote></div></span><p>Not true, take a look at the nested section of the proposal again.</p><p>We discussed that this is valid:</p><pre style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:13.600000381469727px;margin-top:0px;margin-bottom:0px;line-height:1.45;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-wrap:normal;word-break:normal;color:rgb(51,51,51)"><span style="color:rgb(150,152,150)">// Allowed, but pointless.</span>
<span style="color:rgb(150,152,150)">// Identical to Any&lt;ProtocolA, ProtocolB&gt;</span>
<span style="color:rgb(167,29,93)">let</span> b <span style="color:rgb(167,29,93)">:</span> <span style="color:rgb(0,134,179)">Any</span><span style="color:rgb(167,29,93)">&lt;</span><span style="color:rgb(0,134,179)">Any</span><span style="color:rgb(167,29,93)">&lt;</span>ProtocolA, ProtocolB<span style="color:rgb(167,29,93)">&gt;&gt;</span></pre><div><br></div></div> <div>This implies that also this would be valid:</div><div><br></div><div>Any&lt;Any&lt;ClassA, ProtocolA&gt;&gt; inferred as Any&lt;ClassA, ProtocolA&gt;</div></div></blockquote><div><br></div><div>Yes, this is valid.</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"><div><br></div><div>There is another example:</div><div><br></div><div><pre style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:13.600000381469727px;margin-top:0px;margin-bottom:0px;line-height:1.45;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-wrap:normal;word-break:normal;color:rgb(51,51,51)"><span style="color:rgb(150,152,150)">// Can be any type that is a UITableView conforming to ProtocolA.</span>
<span style="color:rgb(150,152,150)">// UITableView is the most specific class, and it is a subclass of the other</span>
<span style="color:rgb(150,152,150)">// two classes.</span>
<span style="color:rgb(167,29,93)">let</span> a <span style="color:rgb(167,29,93)">:</span> <span style="color:rgb(0,134,179)">Any</span><span style="color:rgb(167,29,93)">&lt;</span>UIScrollView, <span style="color:rgb(0,134,179)">Any</span><span style="color:rgb(167,29,93)">&lt;</span>UITableView, <span style="color:rgb(0,134,179)">Any</span><span style="color:rgb(167,29,93)">&lt;</span>UIView, ProtocolA&gt;&gt;&gt;</pre></div><div><br></div><div>Which followed by the mentioned rule can als be:</div><div><br></div><div>Any&lt;UIScrollView, UITableView, Any&lt;UIView, ProtocolA&gt;&gt; or</div><div>Any&lt;UIScrollView, UITableView, UIView, ProtocolA&gt;</div><div><br></div><div>This would force us to allow multiple classes inside Any&lt;…&gt; if there is a inheritance relationship between them.</div></div></blockquote><div><br></div><div>Yes. As explained in the proposal, there is already a way to handle resolving the single &#39;effective&#39; class constraint. You can only &#39;explicitly&#39; declare one class constraint, but you can pull in other class constraints from nested existentials for the sake of making composition easier. In the end it doesn&#39;t matter, because if the class constraints don&#39;t form a valid inheritance hierarchy the compiler will complain, and if they do the most specific type will be chosen.</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"><div><br></div><div>And because this is a inheritance relationship it can be simplified to:</div><div><br></div><div>Any&lt;UITableView, ProtocolA&gt; which is valid. </div><div><br></div><div>And by the way since the order in your proposal would matter, this example won’t work at all, because its not:</div><div><br></div><div>Any&lt;UITableView, Any&lt;UIScrollView, Any&lt;UIView, ProtocolA&gt;&gt;&gt; </div></div></blockquote><div><br></div><div>The order does <b>not</b> affect the semantic meaning of the existential. There is a section in the proposal on how existentials are conceptually &#39;reduced&#39; from whatever form they take when the programmer types them in, please read it. I am not proposing a macro system. The compiler does not do textual replacement in order to flatten nested existential definitions.</div><div><br></div><div>This is also why it makes no sense to have a generic &quot;Any&lt;T, U&gt;&quot;, because such a type is identical to &quot;Any&lt;U, T&gt;&quot;, which is not true for any other generic type or aggregate type in Swift.</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"><div><br></div>In my proposal I explicitly banned multiple reference types and inheritance branches like this. I would need to simplify that type to Any&lt;UITableView, ProtocolA&gt; by myself.<div>Ingeneral this is a good idea, but it makes nesting (with typealiases) almost impossible, when there are some relationship like in the above example.</div><span class=""><div><br></div><div><br> <div><div style="font-family:helvetica,arial;font-size:13px">-- <br>Adrian Zubarev<br>Sent with Airmail</div></div></div></span></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></div>