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

Reply via email to