>From the compilers/runtimes perspective why couldn't the declaration >automatically be included in the main protocol definition as if it was defined >there?
Brandon > On May 20, 2016, at 12:21 PM, Matthew Johnson via swift-evolution > <[email protected]> wrote: > > >> On May 20, 2016, at 11:17 AM, Austin Zheng via swift-evolution >> <[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. > > That would prevent us from adding extension methods to protocols declared in > modules we depend on. This is way to useful to throw away. > >> >> Austin >> >>> On May 20, 2016, at 5:56 AM, Fabian Ehrentraud via swift-evolution >>> <[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. >>>> >>>> Sent from my iPhone >>>> >>>> On 4 Mar 2016, at 08:58, Brent Royal-Gordon <brent at architechies.com> >>>> 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> 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 >> >> _______________________________________________ >> 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
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
