I see your point. I think the core issue here is customizability vs safety.
Allowing users to perform actions in these functions that change the behaviour of a protocol is potentially dangerous, and therefore Swift as a safe language disallows it. This comes at the cost of being able to override the function dynamically and provide a different implementation that is perhaps more appropriate. This limits Swift flexibility. Depending on where you come down on this, it may be "too conservative". Things can only be safe to a certain level and if we keep optimising for safety over functionality, perhaps we'll restrict Swift too much for it to be a useful language. Or perhaps it's a good trade. The decision regarding "closed by default" also had considerations like retrospectively "finalising" or "opening" APIs that made those decisions a little easier. > On 11 Feb 2017, at 3:32 pm, Xiaodi Wu <[email protected]> wrote: > >> On Fri, Feb 10, 2017 at 9:54 PM, Rod Brown <[email protected]> wrote: >> >> >> Sent from my iPhone >> >>> On 11 Feb 2017, at 2:20 pm, Xiaodi Wu <[email protected]> wrote: >>> >>>> On Fri, Feb 10, 2017 at 6:59 PM, Rod Brown <[email protected]> >>>> wrote: >>>> I don't believe these two worlds are in conflict at all. >>>> >>>> We currently have the default only state (without overrides), plus a >>>> conflict. We would simply be adding "override" functionality in part to >>>> clear the conflict. >>>> >>>> With POP the idea is that the protocol, in knowing about how it is >>>> constituted, has a clear pattern for how it implements its behaviours. >>>> Therefore you can leverage the protocol to bear the brunt of the work, >>>> just as we do now. >>>> >>>> The additional tweak to the design of protocols is to allow a user to >>>> define their own implementation where the default is not appropriate, or >>>> is incomplete for the use case. >>> >>> I think I've written a poor explanation of my point. In Swift, it is the >>> library _author_, not the _user_, who gets the final say as to the upper >>> limits on what users can do with the author's types, by using modifiers >>> such as `final` and `open` (or the lack thereof). This has been the subject >>> of vehement opposition but, nonetheless, it is a clear and opinionated >>> decision on the part of the language. What you are critiquing as a bug is >>> regarded as a feature. That is to say, it is a way for the author of a >>> protocol extension method to deny to the user a customization point (in >>> other words, to disallow the outright overriding of the "default" behavior). >>> >>>> This doesn't work against POP - it simply observes that implementations at >>>> times may need to be customised to the use case, and allows that, as an >>>> optional override. >>> >>> Again, the status quo in Swift is that it is up to the protocol's author to >>> determine which methods are overridable by the user and which are not. The >>> idea is that protocol extension methods that are not protocol requirements >>> are the intended way for disallowing such overriding. >>> >>> As to its practical use: this guarantees that if protocol `P` has a method >>> `foo()`, it is possible to invoke `foo()` on an instance of existential >>> type `P` knowing that you will invoke the intended method. A concrete type >>> `T` that conforms to `P` may have its own `foo()` with totally different >>> semantics. After all, if `foo()` is not a protocol requirement, then >>> conforming types can have their own `foo()` do anything at all, with the >>> collision in name being mere coincidence and no guarantee of similar >>> semantics. And, with extensions, some third party can implement such a >>> `foo()` on `T` that the library author has no way of reasoning about. By >>> having a "shadowing" feature for `foo()`, I can know that no matter how >>> anyone in the future extends type `T`, I will invoke the intended `foo()` >>> with the right semantics on an instance of existential type `P`. >>> >>>> It's clear people are trying to do this already because they already have >>>> overrides that are causing this conflict, and thus we are having the >>>> discussion. >>> >>> It sounds like what you are saying is that users of libraries are trying to >>> "override" protocol extension methods that authors of libraries have >>> designed not to be overridden. That this causes problems is, afaict, the >>> intended consequence of this feature and not an overlooked bug. For maximum >>> flexibility, however, Swift allows you to "shadow" the non-overridable >>> method with an identically named method of your own design that can have >>> different semantics. >> >> If the intent is to restrict users and to provide the power to the author of >> the protocol, it appears not just opinionated, but arrogant. >> >> As software developers, we need to work together to provide solutions to use >> cases. This includes not understanding what some use case may be. But >> instead, the consistent argument here has been that software should be as it >> is designed, to hell with the users of the frameworks who may have an >> unknown use case. >> >> This therefore has created the shadow problem, where people implementing a >> protocol end up colliding with the same name, and must make casts back. >> >> Why can't we make an adjustment and allow protocol implementers to define >> the cases where the protocol action is inappropriate. >> >> I believe this argument stems back to the closed-by-default argument on >> classes with "public" and shows a concerning trend in how Swift is being >> developed. We cannot look at Swift purely from the perspective of the >> Standard Library, or one framework, or one implementer. It is how we >> coordinate between framework authors that we end up creating a unified >> system. >> >> It should never be a feature to make users of frameworks fight with writers >> of frameworks. That's just absurd. > > That's an unfair characterization. Certainly, `public` vs `open` was hotly > debated, but the Swift core team came down on one side of that debate after > weighing all the arguments. As you say, this functionality of protocol > extension members is of a kind to that decision, and in fact it pre-dates > that decision. > > Let's be clear that it's not about making users of libraries "fight" with > authors of libraries. In a language where a user can retroactively extend a > type, these facilities can be critical for allowing library authors to reason > about their own code. These guarantees aren't only for the original author, > either. See the currently ongoing thread about introducing a `closed` keyword > and how knowledge about restrictions on how a class, enum, struct, or > protocol can be changed by another party can help any user reason about their > own code. As you can see above, I offered an example where even an end user > can rely on `P.foo()` to do the same intended thing (where `P` is a protocol) > no matter how anyone else extends a conforming type `T`. This is not at all > absurd but a practical boon. > > Can it be inconvenient if you happen to be the user of a type `P` and want a > customization point where the author has not designed one? Sure. But no more > so than if you happen to be the user of a type `P` and want to access a > private member where the author has decided not to make it public. If we deem > this all absurd we'd not have access modifiers either, and we'd abandon all > the work on the roadmap about library resilience, which can also constrain > library authors to allow more freedom for library users. > >>>> In this case, I don't see overriding the protocol "default" as working >>>> against this world - I think it clarifies it. >>>> >>>> Rod >>> >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
