on Fri May 20 2016, Fabian Ehrentraud <[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/ > > 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. Being in the run-up to WWDC, I don't really have the time to participate in this discussion right now, although I think it is important and interesting. However, this last sentence caught my eye and I thought I should clarify something: protocols unify static and dynamic dispatch, and one is not inherently better than the other. They have different strengths. Protocol-oriented programming is about leveraging those strengths appropriately, not about a mandate to choose one or the other form of dispatch. > > > 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] > https://lists.swift.org/mailman/listinfo/swift-evolution -- -Dave _______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
