<div dir="ltr">I'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"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></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<T, U>(_ a: T, _ b: U) -> Set<Any<T, U>>? { /* merge somehow if possible */ }</div></div></blockquote><div><br></div><div>You would not be able to form Any<T, U> 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<…> 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<> existential as the proposal stands.</div><div><br></div><div>This doesn't currently work in Swift, and it shouldn't: "func foo<A, B>() -> protocol<A, B>". 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<T: UIView>(value: Any<T, SomeProtocol>)</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<UIView, SomeProtocol>)</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<UIView, ProtocolA> where T == UIView and U == ProtocolA</div><div style="margin:0px">let merged_1: Set<Any<UIView, ProtocolA>> = 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<Any<UIView, ProtocolA>> = unionIfPossible(shadowedButton, button) </div><div style="margin:0px"><br></div><div style="margin:0px">Any<UIView, ProtocolA> != Any<ProtocolA, UIView> 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">"Can be any class type that is a UIView or a subclass of UIView, that also conforms to ProtocolA.“ == "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<…>`.</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<A, Any<ClassB, ProtocolA>> == A != Any<Any<ClassB, ProtocolA>, A> == Any<ClassB, ProtocolA, A> which should be reorder by the compiler and inferred as A</div></div></div></blockquote><div><br></div><div>`Any<Any<ClassB, ProtocolA>, A>` is not allowed because if a class is provided it must come first.</div><div><br></div><div>`<span>Any<ClassB, ProtocolA, A>` 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,'Liberation Mono',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<ProtocolA, ProtocolB></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)"><</span><span style="color:rgb(0,134,179)">Any</span><span style="color:rgb(167,29,93)"><</span>ProtocolA, ProtocolB<span style="color:rgb(167,29,93)">>></span></pre><div><br></div></div> <div>This implies that also this would be valid:</div><div><br></div><div>Any<Any<ClassA, ProtocolA>> inferred as Any<ClassA, ProtocolA></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,'Liberation Mono',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)"><</span>UIScrollView, <span style="color:rgb(0,134,179)">Any</span><span style="color:rgb(167,29,93)"><</span>UITableView, <span style="color:rgb(0,134,179)">Any</span><span style="color:rgb(167,29,93)"><</span>UIView, ProtocolA>>></pre></div><div><br></div><div>Which followed by the mentioned rule can als be:</div><div><br></div><div>Any<UIScrollView, UITableView, Any<UIView, ProtocolA>> or</div><div>Any<UIScrollView, UITableView, UIView, ProtocolA></div><div><br></div><div>This would force us to allow multiple classes inside Any<…> 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 'effective' class constraint. You can only 'explicitly' 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't matter, because if the class constraints don'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<UITableView, ProtocolA> 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<UITableView, Any<UIScrollView, Any<UIView, ProtocolA>>> </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 'reduced' 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 "Any<T, U>", because such a type is identical to "Any<U, T>", 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<UITableView, ProtocolA> 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>