<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div>Hello Dave,</div><div><br><div>Sent from my iPhone</div></div><div><br>On 13 Jun 2016, at 03:04, Dave Abrahams via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> wrote:<br><br></div><blockquote type="cite"><div><span></span><br><span>on Fri Jun 10 2016, Thorsten Seitz <<a href="http://tseitz42-at-icloud.com">tseitz42-AT-icloud.com</a>> wrote:</span><br><span></span><br><blockquote type="cite"><blockquote type="cite"><span>Am 09.06.2016 um 19:50 schrieb Thorsten Seitz via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>>:</span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>Am 09.06.2016 um 18:49 schrieb Dave Abrahams via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>>:</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>on Wed Jun 08 2016, Jordan Rose <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> wrote:</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution</span><br></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span><<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> wrote:</span><br></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>on Wed Jun 08 2016, Thorsten Seitz</span><br></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span><<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a></span><br></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span><<a href="mailto:swift-evolution@swift.org">mailto:swift-evolution@swift.org</a>>></span><br></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>wrote:</span><br></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>Ah, thanks, I forgot! I still consider this a bug, though (will have</span><br></blockquote></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>to read up again what the reasons are for that behavior).</span><br></blockquote></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>Yes, but in the case of the issue we're discussing, the choices are:</span><br></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>1. Omit from the existential's API any protocol requirements that depend</span><br></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>on Self or associated types, in which case it *can't* conform to</span><br></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>itself because it doesn't fulfill the requirements.</span><br></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>2. Erase type relationships and trap at runtime when they don't line up.</span><br></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>Matthew has been arguing against #2, but you can't “fix the bug” without</span><br></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>it.</span><br></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>#1 has been my preference for a while as well, at least as a starting</span><br></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>point. </span><br></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>I should point out that with the resyntaxing of existentials to</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>Any<Protocols...>, the idea that Collection's existential doesn't</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>conform to Collection becomes far less absurd than it was, so maybe this</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><span>is not so bad.</span><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span>I think the problem is more that Any<Collection> does not conform to</span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span>a specific value for a type parameter T: Collection</span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span>What I mean by this is that `Collection` denotes a type family, a</span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span>generic parameter `T: Collection` denotes a specific (though</span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span>unknown) member of that type family and `Any<Collection>` denotes</span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span>the type family again, so there is really no point in writing</span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span>Any<Collection> IMO.</span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span>The type family cannot conform to T because T is just one fixed member of it.</span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span>It conforms to itself, though, as I can write</span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span>let c1: Any<Collection> = …</span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span>let c2: Any<Collection> = c1</span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span></span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span>That’s why I think that we could just drop Any<Collection> and simply write Collection.</span><br></blockquote></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>Let me expand that a bit:</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>Actually all this talk about existentials vs. generics or protocols</span><br></blockquote><blockquote type="cite"><span>vs. classes has had me confused somewhat and I think there are still</span><br></blockquote><blockquote type="cite"><span>some misconceptions present on this list sometimes, so I’ll try to</span><br></blockquote><blockquote type="cite"><span>clear them up:</span><br></blockquote><span></span><br><span>There are several objectively incorrect statements here, and several</span><br><span>others with which I disagree. I was hoping someone else would write</span><br><span>this for me, but since the post has such a tone of authority I feel I</span><br><span>must respond.</span><br><span></span><br><blockquote type="cite"><span>(1) misconception: protocols with associated types are somehow very</span><br></blockquote><blockquote type="cite"><span>different from generics</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>I don’t think they are and I will explain why. The only difference is</span><br></blockquote><blockquote type="cite"><span>the way the type parameters are bound: generics use explicit parameter</span><br></blockquote><blockquote type="cite"><span>lists whereas protocols use inheritance. That has some advantages</span><br></blockquote><blockquote type="cite"><span>(think long parameter lists of generics) and some disadvantages.</span><br></blockquote><blockquote type="cite"><span>These ways are dual in a notation sense: generic types have to have</span><br></blockquote><blockquote type="cite"><span>all parameters bound whereas protocols cannot bind any of them.</span><br></blockquote><blockquote type="cite"><span>The „existential“ notation `Any<>` being discussed on this list is</span><br></blockquote><blockquote type="cite"><span>nothing more than adding the ability to protocols to bind the</span><br></blockquote><blockquote type="cite"><span>parameters to be used just like Java’s wildcards are adding the</span><br></blockquote><blockquote type="cite"><span>opposite feature to generics, namely not having to bind all</span><br></blockquote><blockquote type="cite"><span>parameters.</span><br></blockquote><span></span><br><span>Protocols and generics fulfill completely different roles in Swift, and</span><br><span>so, **especially in a language design context like the one we're in</span><br><span>here**, must be thought of differently. The former are an abstraction</span><br><span>mechanism for APIs, and the latter a mechanism for generalizing</span><br><span>implementations. The only place you could argue that they intersect is</span><br><span>in generic non-final classes, because a class fills the dual role of</span><br><span>abstraction and implementation mechanism (and some might say that's a</span><br><span>weakness). But even accounting for generic classes, protocols with</span><br><span>associated types are very different from generics. Two utterly</span><br><span>different types (an enum and a struct, for example) can conform to any</span><br><span>given protocol P, but generic types always share a common basis</span><br><span>implementation. There is no way to produce distinct instances of a</span><br><span>generic type with all its type parameters bound, but for any protocol P</span><br><span>I can make infinitely many instances of P with P.AssociatedType == Int.</span><br><span></span><br><span>Back to the my original point: while protocols and generic types have</span><br><span>some similarities, the idea that they are fundamentally the same thing</span><br><span>(I know you didn't say *exactly* that, but I think it will be read that</span><br><span>way) would be wrong and a very unproductive way to approach language</span><br><span>evolution.</span><br><span></span><br><blockquote type="cite"><span>Essentially `Any<Collection>` in Swift is just the same as</span><br></blockquote><blockquote type="cite"><span>`Collection<?>` in Java (assuming for comparability’s sake that</span><br></blockquote><blockquote type="cite"><span>Swift’s Collection had no additional associated types; otherwise I</span><br></blockquote><blockquote type="cite"><span>would just have to introduce a Collection<Element, Index> in Java).</span><br></blockquote><span></span><br><span>I don't see how you can use an example that requires *assuming away*</span><br><span>assoociated types to justify an argument that protocols *with associated</span><br><span>types* are the same as generics.</span><br><span></span><br><blockquote type="cite"><span>Likewise `Any<Collection where .Element: Number>` is just the same as</span><br></blockquote><blockquote type="cite"><span>`Collection<? extends Number>` in Java.</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>And just like Collection<?> does not conform to a type parameter `T</span><br></blockquote><blockquote type="cite"><span>extends Collection<?>` because Collection<?> is the type `forall</span><br></blockquote><blockquote type="cite"><span>E. Collection<E>` whereas `T extends Collection<?>` is the type</span><br></blockquote><blockquote type="cite"><span>`T. Collection<T>` for a given T.</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>In essence protocols with associated types are like generics with</span><br></blockquote><blockquote type="cite"><span>wildcards.</span><br></blockquote><span></span><br><span>It is true that generics with wildcards in Java *are* (not just “like”)</span><br><span>existential types but I don't agree with the statement above. Because</span><br><span>Java tries to create an “everything is a class” world, generic classes</span><br><span>with bound type parameters end up playing the role of existential type.</span><br><span>But protocols in Swift are not, fundamentally, just existential types,</span><br><span>and the resyntaxing of ProtocolName to Any<ProtocolName> for use in type</span><br><span>context is a huge leap forward in making that distinction clear... when</span><br><span>that's done (unless we leave Array<ProtocolName> around as a synonym for</span><br><span>Array<Any<ProtocolName>>—I really hope we won't!) protocols indeed</span><br><span>*won't* be types at all, existential or otherwise.</span><br><span></span><br><blockquote type="cite"><span>Coming back to the questions whether (a) allowing existentials to be</span><br></blockquote><blockquote type="cite"><span>used as types is useful </span><br></blockquote><span></span><br><span>That's the only use existentials have. They *are* types. Of course</span><br><span>they're useful, and I don't think anyone was arguing otherwise.</span><br><span></span><br><blockquote type="cite"><span>and (b) whether sacrificing type safety would somehow be necessary for</span><br></blockquote><blockquote type="cite"><span>that, I think we can safely answer (a) yes, it *is* useful to be able</span><br></blockquote><blockquote type="cite"><span>to use existentials like Any<Collection> as types, because wildcards</span><br></blockquote><blockquote type="cite"><span>are quite often needed and very useful in Java (they haven’t been</span><br></blockquote><blockquote type="cite"><span>added without a reason) (b) no, sacrificing type safety does not make</span><br></blockquote><blockquote type="cite"><span>sense, as the experience with Java’s wildcards shows that this is not</span><br></blockquote><blockquote type="cite"><span>needed. </span><br></blockquote><span></span><br><span>I would call this “interesting information,” but hardly conclusive.</span><br><span>Java's generics are almost exactly the same thing as Objective-C</span><br><span>lightweight generics, which are less capable and less expressive in</span><br><span>many ways than Swift's generics. </span><br><span></span><br><blockquote type="cite"><span>Especially if something like path dependent types is used like</span><br></blockquote><blockquote type="cite"><span>proposed and some notation to open an existential’s type is added,</span><br></blockquote><blockquote type="cite"><span>which is both something that Java does not have.</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>(2) misconception: POP is different from OOP</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>It is not. Protocols are just interfaces using subtyping like OOP has</span><br></blockquote><blockquote type="cite"><span>always done. They just use associated types instead of explicit type</span><br></blockquote><blockquote type="cite"><span>parameters for generics (see above). </span><br></blockquote><span></span><br><span>They are not the same thing at all (see above ;->). To add to the list</span><br><span>above, protocols can express fundamental relationships—like Self</span><br><span>requirements—that OOP simply can't handle. There's a reason Java can't</span><br><span>express Comparable without losing static type-safety. Finally, in a</span><br><span>language with first-class value types, taking a protocol-oriented</span><br><span>approach to abstraction leads to *fundamentally* different designs from</span><br><span>what you get using OOP.</span><br><span></span><br><blockquote type="cite"><span>The more important distinction of Swift is emphasizing value types and</span><br></blockquote><blockquote type="cite"><span>making mutation safely available by enforcing copy semantics for value</span><br></blockquote><blockquote type="cite"><span>types. </span><br></blockquote><span></span><br><span>We don't, in fact, enforce copy semantics for value types. </span></div></blockquote><div><br></div><div>It was again clarified that Copy on Write was only automatically added for Strings and Arrays, and subclasses I suppose, but how else are structs passed around if not by copy? If they are passed around by reference and people are starting, being encouraged to do so, to massively make use of structs... will enforcing copy semantics (even with opt-in CoW behaviour) be a massive cause of performance regression in games and similar kinds of tight processing loops? </div><br><blockquote type="cite"><div><span>That's</span><br><span>something I'd like to change. But regardless, value types would be a</span><br><span>*lot* less useful if they couldn't conform to protocols, and so they</span><br><span>would be a lot less used. Heck, before we got protocol extensions in</span><br><span>Swift 2, there was basically *no way* to share implementation among</span><br><span>value types. </span></div></blockquote><div><br></div><div>Ah so it is their (value types) fault our beautiful abstract API contracts meant to decouple behaviour from implementation now contain code and this implementation ;)?</div><div><br></div><div>The other day I was revisiting the rationale by Java engineers for default methods in Java interfaces, which I always used to compare Objective-C protocols to, and beside from the ease of adding code to a lot of pre-existing objects without forcing developers using a library to have to do much to adapt to a new update of said library... Well, I did not actually find much beyond convenience. </div><div>In Swift, they are already enabling structs to do something you could have only done with classes before (sharing implementation): in a way it is kind of forcing people to use composition over subclassing without as much effort as before.</div><div><br></div><div>Still, I appreciated how clear dispatching/overriding rules were designed (although they may be limiting for some use cases people here might conceive):</div><div><div></div><blockquote type="cite"><div>When you extend an interface that contains a default method, you can do the following:</div><div><b>* Not mention the default method at all, which lets your extended interface inherit the default method.</b></div><div><b>* Redeclare the default method, which makes it abstract.</b></div><div><b>* Redefine the default method, which overrides it.</b></div></blockquote><div><a href="https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html">https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html</a></div></div><div><br></div><div>I find that quite intuitive to adapt to. What I would like to ask you is this: don't you feel it is dangerous or at least unintuitive that casting generally does not allow to change how the object behaves (it does not interfere with the object's implementation of its API contract) while if you are using default methods in protocol extensions you are suddenly allowing casting to change the class implementation?</div><div><br></div><div>Are extensions and in particular default methods meant more for value types, implementation sharing too as you were saying, than classes?</div><br><blockquote type="cite"><div><span>So you can't take protocols out of the picture without</span><br><span>making value types, and the argument for value semantics, far weaker.</span><br><span></span><br><blockquote type="cite"><span>But protocols are not really different from interfaces in Java. </span><br></blockquote><blockquote type="cite"><span>I would have preferred a unified model using just classes with real</span><br></blockquote><blockquote type="cite"><span>multiple inheritance like Eiffel has and value types just being a part</span><br></blockquote><blockquote type="cite"><span>of that similar to Eiffel’s `expanded` classes. But that ship has</span><br></blockquote><blockquote type="cite"><span>probably sailed a long time ago :-/ So be it. But at least there</span><br></blockquote><blockquote type="cite"><span>should be no reasons for POP vs OOP wars ;-) (I’d like to add that I</span><br></blockquote><blockquote type="cite"><span>liked Dave’s talks at last WWDC very much, it’s just that I don’t</span><br></blockquote><blockquote type="cite"><span>think that POP is something new or different.)</span><br></blockquote><span></span><br><span>Protocol-oriented programming is about the synergy of features and ideas</span><br><span>most of which not *individually* new, but that together create a new</span><br><span>world of possibilities. I've already discussed the synergy of protocols</span><br><span>and first-class value semantics. There's also the fact that in</span><br><span>protocols we have one construct with which to express dynamic</span><br><span>polymorphism (existentials) and static polymorphism (generic</span><br><span>constraints), both of which have important roles to play but that I</span><br><span>maintain are very different indeed. One result is that you can “start</span><br><span>with a protocol” as your abstraction mechanism and know that you're not</span><br><span>going to design yourself into a corner where it becomes impossibly</span><br><span>awkward to express what you need. Finally—and I'm certain this *is*</span><br><span>new—in protocol extensions we have a means to express both post-hoc</span><br><span>conformance and generic functions that is much more accessible to users</span><br><span>than in any previous language, to the point where generic programming</span><br><span>can become a natural part of everyday work.</span><br><span></span><br><span>-- </span><br><span>Dave</span><br><span>_______________________________________________</span><br><span>swift-evolution mailing list</span><br><span><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></div></blockquote></body></html>