> On May 20, 2016, at 12:12 PM, Brandon Knope via swift-evolution > <[email protected]> wrote: > > > > On May 20, 2016, at 12:46 PM, David Waite via swift-evolution > <[email protected] <mailto:[email protected]>> wrote: > >> >>> On May 20, 2016, at 10:17 AM, Austin Zheng via swift-evolution >>> <[email protected] <mailto:[email protected]>> wrote: >>> >>> I almost want to propose forbidding methods in protocol extensions unless >>> they're also a requirement in the protocol itself, but I don't think that >>> would fly. >>> >>> Austin >> >> Thats one option. >> >> Think two separate developers - only who implements the protocol Foo and has >> an independent bar() method on their type, and one who writes an extension >> to Foo to add a bar method on it. >> >> bar() is not part of the protocol specification. the person implementing the >> type has no idea that others are expecting his bar() to meet particular >> requirements, just because it was declared in a protocol extension. >> > > How is this the case? Don't you have to expect that others can use your > protocol extension since it is visible to them?
If the conforming type is implemented in a separate module from the protocol extension that extension *is not* visible to them. They would have no expectation that their `bar` method had anything to do with the protocol which *is* visible to them in its originally declared form. > > I think the static behavior should be an opt in feature so the common case is > what everyone expects to happen. A big part of the problem is that there are different perspectives on what is actually expected. > > >> So silently using the type implementor’s bar() method when using Foo is >> unacceptable. You don’t know if it meets the requirements, because Foo never >> specified requirements for a bar() method. >> >> BTW, it would also be dangerous to let an extension make a protocol >> implement another protocol for similar reasons. >> >> So, options to solve: >> - Having the extension to protocol Foo only apply when dealing in terms of >> Foo type and not the implementors type. This sounds less useful than what we >> have today. >> - You could have a warning if the compiler sees a Foo extension and a Foo >> implementation both with bar(). Hopefully the application developer has >> control over either the protocol definition, the extension, or the >> implementation of the protocol to try and resolve it. >> - forbid protocol extensions adding methods - they can only implement >> existing methods >> - If protocol implementations used “override” (or perhaps a better named >> keyword for covering this instance as well like “implement”), you could >> consider protocol extensions to extend the protocol definition more safely. >> You would also catch the case where the Protocol definition changed to >> include the same foo() method the implementing type defined independently, >> so the implementor can make sure their version of foo() meets the >> requirements the protocol gives. >> >> -DW >>> >>>> On May 20, 2016, at 5:56 AM, Fabian Ehrentraud via swift-evolution >>>> <[email protected] <mailto:[email protected]>> wrote: >>>> >>>> Hi, >>>> >>>> there's been a little discussion about static vs. dynamic dispatch on this >>>> mailing list, and there is a good post about the pitfalls when using >>>> attributes defined in extensions [1]. >>>> >>>> Having run into this myself during development, is there a plan on how to >>>> reduce the pitfalls in future versions of Swift? >>>> >>>> - Fabian >>>> >>>> >>>> [1] >>>> https://developer.ibm.com/swift/2016/01/27/seven-swift-snares-how-to-avoid-them/ >>>> >>>> <https://developer.ibm.com/swift/2016/01/27/seven-swift-snares-how-to-avoid-them/> >>>> >>>>> Sorry, I understand and appreciate your pragmatism. Right now it feels >>>>> very much like a fight to the ideological death between POP and OOP and >>>>> it may get really bad results this way. >>>>> >>>>> Sent from my iPhone >>>>> >>>>> On 4 Mar 2016, at 08:58, Brent Royal-Gordon <brent at architechies.com >>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>> wrote: >>>>> >>>>> >> Brent, why is dynamic dispatching for protocol extension default >>>>> >> implementations wrong in your mind? Wouldn't you agree that when >>>>> >> static dispatching introduces such a side effect that it should not be >>>>> >> automatically applied and perhaps a keyword should be added if you >>>>> >> really wanted static dispatching nonetheless? >>>>> >> >>>>> >> I think that code execution should not be affected by type casting, it >>>>> >> feels like a very confusing part of the language. >>>>> > >>>>> > I don't think dynamic dispatch is wrong; I think it's a large and >>>>> > technically challenging change. So in the spirit of incrementalism, I >>>>> > was trying to make cautious proposals which kept existing semantics >>>>> > intact but made them clearer, in preparation for perhaps eventually >>>>> > introducing dynamic dispatch. (Basically, I suggested that >>>>> > non-overridable protocol extension members should be marked `final` and >>>>> > it should be illegal to shadow them.) >>>>> > >>>>> > But the feedback I got indicated that most people wanted a more >>>>> > aggressive proposal which introduced dynamic dispatch immediately. >>>>> > That's much harder to propose because it touches on all sorts of >>>>> > runtime implementation details I know nothing about, so I didn't try to >>>>> > draft a proposal. >>>>> > >>>>> > (You are, perhaps inadvertently, currently demonstrating exactly what >>>>> > happened in those previous threads!) >>>>> > >>>>> > -- >>>>> > Brent Royal-Gordon >>>>> > Architechies >>>>> > >>>> >>>>> > On Dec 11, 2015, at 8:56 PM, Kevin Ballard via swift-evolution >>>>> > <swift-evolution at swift.org >>>>> > <https://lists.swift.org/mailman/listinfo/swift-evolution>> wrote: >>>>> > >>>>> > You think that Swift prefers virtual dispatch. I think it prefers >>>>> > static. >>>>> > >>>>> > I think what's really going on here is that _in most cases_ there's no >>>>> > observable difference between static dispatch and virtual dispatch. If >>>>> > you think of Swift as an OOP language with a powerful value-typed >>>>> > system added on, then you'll probably think Swift prefers virtual >>>>> > dispatch. If you think of Swift as a value-typed language with an OOP >>>>> > layer added, then you'll probably think Swift prefers static dispatch. >>>>> > In reality, Swift is a hybrid language and it uses different types of >>>>> > dispatch in different situations as appropriate. >>>>> >>>>> (emphasis mine) >>>>> >>>>> I know that this is a bit philosophical, but let me suggest a “next level >>>>> down” way to look at this. Static and dynamic are *both* great after >>>>> all, and if you’re looking to type-cast languages, you need to consider >>>>> them both in light of their semantics, but also factor in their >>>>> compilation strategy and the programmer model that they all provide. Let >>>>> me give you some examples, but keep in mind that this is a narrow view >>>>> and just MHO: >>>>> >>>>> 1. C: Static compilation model, static semantics. While it does provide >>>>> indirect function pointers, C does everything possible to punish their >>>>> use (ever see the non-typedef'd prototype for signal(3/7)?), and is >>>>> almost always statically compiled. It provides a very “static centric” >>>>> programming model. This is great in terms of predictability - it makes >>>>> it trivial to “predict” what your code will look like at a machine level. >>>>> >>>>> 2. Javascript: Completely dynamic compilation model, completely dynamic >>>>> semantics. No one talks about statically compiling javascript, because >>>>> the result of doing so would be a really really slow executable. >>>>> Javascript performance hinges on dynamic profile information to be able >>>>> to efficiently execute a program. This provides a very “dynamic centric” >>>>> programming model, with no ability to understand how your code executes >>>>> at a machine level. >>>>> >>>>> 3. C++: C++ is a step up from C in terms of introducing dynamism into the >>>>> model with virtual functions. Sadly, C++ also provides a hostile model >>>>> for static optimizability - the existence of placement new prevents a lot >>>>> of interesting devirtualization opportunities, and generally makes the >>>>> compiler’s life difficult. OTOH, like C, C++ provides a very predictable >>>>> model: C++ programmers assume that C constructs are static, but virtual >>>>> methods will be dynamically dispatched. This is correct because (except >>>>> for narrow cases) the compiler has to use dynamic dispatch for C++ >>>>> virtual methods. The good news here is that its dynamism is completely >>>>> opt in, so C++ preserves all of the predictability, performance, and >>>>> static-compilability of C while providing a higher level programming >>>>> model. If virtual methods are ever actually a performance problem, a C++ >>>>> programmer has ways to deal with that, directly in their code. >>>>> >>>>> 4. Java: Java makes nearly "everything" an object (no structs or other >>>>> non-primitive value types), and all methods default to being “virtual” >>>>> (in the C++ sense). Java also introduces interfaces, which offer an >>>>> added dimension on dynamic dispatch. To cope with this, Java assumes a >>>>> JIT compilation model, which can use dynamic behavior to de-virtualize >>>>> the (almost always) monomorphic calls into checked direct calls. This >>>>> works out really well in practice, because JIT compilers are great at >>>>> telling when a program with apparently very dynamic semantics actually >>>>> have static semantics in practice (e.g. a dynamic call has a single >>>>> receiver). OTOH, since the compilation model assumes a JIT, this means >>>>> that purely “AOT” static compilers (which have no profile information, no >>>>> knowledge of class loaders, etc) necessarily produce inferior code. It >>>>> also means that Java doesn’t “scale down” well to small embedded systems >>>>> that can’t support a JIT, like a bootloader. >>>>> >>>>> 5) Objective-C: Objective-C provides a hybrid model which favors >>>>> predictability due to its static compilation model (similar in some ways >>>>> to C++). The C-like constructs provide C-like performance, and the >>>>> “messaging” constructs are never “devirtualized”, so they provide very >>>>> predictable performance characteristics. Because it is predictable, if >>>>> the cost of a message send ever becomes an issue in practice, the >>>>> programmer has many patterns to deal with it (including "imp caching", >>>>> and also including the ability to define the problem away by rewriting >>>>> code in terms of C constructs). The end result of this is that >>>>> programmers write code which use C-level features where performance >>>>> matters and dynamicism doesn’t, but use ObjC features where dynamicism is >>>>> important or where performance doesn’t matter. >>>>> >>>>> While it would be possible to implement a JIT compiler for ObjC, I’d >>>>> expect the wins to be low, because the “hot” code which may be hinging on >>>>> these dynamic features is likely to already be optimized by hand. >>>>> >>>>> 6) GoLang: From this narrow discussion and perspective, Go has a hybrid >>>>> model that has similar characteristics to Objective-C 2013 (which >>>>> introduced modules, but didn’t yet have generics). It assumes static >>>>> compilation and provides a very predictable hybrid programming model. >>>>> Its func’s are statically dispatched, but its interfaces are dynamically >>>>> dispatched. It doesn’t provide guaranteed dynamic dispatch (or >>>>> “classes") like ObjC, but it provides even more dynamic feautres in other >>>>> areas (e.g. it requires a cycle-collecting garbage collector). Its >>>>> "interface{}” type is pretty equivalent to “id” (e.g. all uses of it are >>>>> dynamically dispatched or must be downcasted), and it encourages use of >>>>> it in the same places that Objective-C does. Go introduces checked >>>>> downcasts, which introduce some run-time overhead, but also provide >>>>> safety compared to Objective-C. Go thankfully introduces a replacement >>>>> for the imperative constructs in C, which defines away a bunch of C >>>>> problems that Objective-C inherited, and it certainly is prettier! >>>>> >>>>> … I can go on about other languages, but I have probably already gotten >>>>> myself into enough trouble. :-) >>>>> >>>>> >>>>> With this as context, lets talk about Swift: >>>>> >>>>> Swift is another case of a hybrid model: its semantics provide >>>>> predictability between obviously static (structs, enums, and global >>>>> funcs) and obviously dynamic (classes, protocols, and closures) >>>>> constructs. A focus of Swift (like Java and Javascript) is to provide an >>>>> apparently simple programming model. However, Swift also intentionally >>>>> "cheats" in its global design by mixing in a few tricks to make the >>>>> dynamic parts of the language optimizable by a static compiler in many >>>>> common cases, without requiring profiling or other dynamic information.. >>>>> For example, the Swift compiler can tell if methods in non-public classes >>>>> are never overridden (and non-public is the default, for a lot of good >>>>> reasons) - thus treating them as final. This allows eliminating much of >>>>> the overhead of dynamic dispatch without requiring a JIT. Consider an >>>>> “app”: because it never needs to have non-public classes, this is >>>>> incredibly powerful - the design of the swift package manager extends >>>>> this even further (in principle, not done yet) to external libraries. >>>>> Further, Swift’s generics provide an a static performance model similar >>>>> to C++ templates in release builds (though I agree we need to do more to >>>>> really follow through on this) -- while Swift existentials (values of >>>>> protocol type) provide a balance by giving a highly dynamic model. >>>>> >>>>> The upshot of this is that Swift isn’t squarely in either of the static >>>>> or dynamic camps: it aims to provide a very predictable performance model >>>>> (someone writing a bootloader or firmware can stick to using Swift >>>>> structs and have a simple guarantee of no dynamic overhead or runtime >>>>> dependence) while also providing an expressive and clean high level >>>>> programming model - simplifying learning and the common case where >>>>> programmers don’t care to count cycles. If anything, I’d say that Swift >>>>> is an “opportunistic” language, in that it provides a very dynamic >>>>> “default" programming model, where you don’t have to think about the fact >>>>> that a static compiler is able to transparently provide great performance >>>>> - without needing the overhead of a JIT. >>>>> >>>>> Finally, while it is possible that a JIT compiler might be interesting >>>>> someday in the Swift space, if we do things right, it will never be >>>>> “worth it” because programmers will have enough ability to reason about >>>>> performance at their fingertips. This means that there should be no Java >>>>> or Javascript-magnitude "performance delta" sitting on the table waiting >>>>> for a JIT to scoop up. We’ll see how it works out long term, but I think >>>>> we’re doing pretty well so far. >>>>> >>>>> TL;DR: What I’m really getting at is that the old static vs dynamic trope >>>>> is at the very least only half of the story. You really need to include >>>>> the compilation model and thus the resultant programmer model into the >>>>> story, and the programmer model is what really matters, IMHO. >>>>> >>>>> -Chris >>>> >>>> _______________________________________________ >>>> swift-evolution mailing list >>>> [email protected] <mailto:[email protected]> >>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>> >>> _______________________________________________ >>> swift-evolution mailing list >>> [email protected] <mailto:[email protected]> >>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >> >> _______________________________________________ >> swift-evolution mailing list >> [email protected] <mailto:[email protected]> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> <https://lists.swift.org/mailman/listinfo/swift-evolution> > _______________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
