I'm not sure I understand. What compiler or language support is missing for StringCore? On Tue, Sep 20, 2016 at 16:42 Karl via swift-evolution < swift-evolution@swift.org> wrote:
> On 20 Sep 2016, at 23:28, Karl <raziel.im+swift-...@gmail.com> wrote: > > > On 20 Sep 2016, at 18:43, Nevin Brackett-Rozinsky via swift-evolution < > swift-evolution@swift.org> wrote: > > I have been following this discussion (as well as similar threads earlier > this year) and listening to the ideas put forth by all sides. > > It seems to me that the fundamental difference between classes and > protocols is that classes inherit implementation whereas protocol > conformance is a promise about interface. > > When a class or struct or enum declares itself as conforming to a > protocol, that means it has all the members specified in the protocol. The > protocol conformance simply codifies a fact about the type itself: namely > that all those members are present. > > In this model, any keyword such as `implements` on each conforming member > would introduce substantial boilerplate for negligible gain. The purpose of > a protocol is to communicate that certain members are available, not to > make declaring those members more onerous. > > However, default implementations for protocols blur the line. Now there is > actual implementation being inherited. A conforming type may choose to roll > its own version of a method, or to utilize the default provided by the > protocol. This is closer to the situation with subclassing. > > Moreover, a protocol which conforms to another protocol may itself define > (or redefine!) default implementations for members of that other protocol. > This can create “inheritance chains” of protocol default implementations. I > think there is value in being able to refer to (and call) the inherited > default implementation through some sort of `super` functionality. > > On the other hand, the existence of a default implementation in a protocol > is in large part merely a convenience: a courtesy so that each conforming > type need not rewrite the same boilerplate code. > > A type which conforms to a protocol may accept the default or it may > provide its own implementation, but it is not “overriding” anything. The > default implementation was offered as a convenience, to be taken or left as > needed. Thus I do not think any keyword (neither `override` nor > `implements`) should be required in that case either. > > The frequently-raised point regarding near-miss member names deserves some > attention. Several people have expressed a desire for the compiler to > assist them in determining whether a given member does or does not meet a > protocol requirement. Specifically, when a type conforms to a protocol with > a default implementation, and the type defines a member with a similar > signature, it is not obvious at glance if that member matches the protocol. > > I think this is a job for linters and IDEs. For example, syntax > highlighting could distinguish members which satisfy a protocol > requirement, thereby providing immediate visual confirmation of success. > > Having followed the lengthy discussion and weighed the numerous ideas put > forth, I come down firmly on the side of no keyword for protocol > conformance. > > A protocol describes an interface and provides a set of customization > points. It may also, as a convenience, offer default implementations. The > protocol simply describes the capabilities of its conforming types, and any > default implementations are there to make things easier for them. > > Conforming types should not be afflicted with extraneous keywords: that > would run contrary to the purpose of having protocols in the first place. > > Nevin > > > On Tue, Sep 20, 2016 at 11:16 AM, Xiaodi Wu via swift-evolution < > swift-evolution@swift.org> wrote: > >> As I mentioned above, I agree that better diagnostics for near-misses are >> necessary, but they are possible without new syntax. There is no win in >> avoiding unintentional behavior because, without a default implementation, >> these issues are caught at compile time already. >> >> On Tue, Sep 20, 2016 at 10:14 Vladimir.S via swift-evolution < >> swift-evolution@swift.org> wrote: >> >>> >>> > extension P { >>> > implement func foo() -> [String : String] { return [:] } >>> > } >>> >>> Yes, it seems like we need `implement` (or `override` as another >>> suggestion) in protocol extension also just for the same reasons - be >>> clear >>> about our intention regarding implementing the requirement, to show that >>> this func *depends* on the previous definition of P protocol and to avoid >>> possible mistakes related to protocol conformance. >>> >>> On 20.09.2016 17:38, Charles Srstka wrote: >>> >> On Sep 20, 2016, at 8:17 AM, Vladimir.S via swift-evolution >>> >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >>> >> >>> >> On 20.09.2016 3:03, Xiaodi Wu via swift-evolution wrote: >>> >>> I definitely think Vladimir's suggestion is a great starting point, >>> IMO. >>> >>> >>> >>> However, I think it could be improved in one key respect where >>> previous >>> >>> proposals using `override` are superior. Namely, the proposed >>> `implement` >>> >>> keyword adds no additional safety when a type implements a protocol >>> >>> requirement that doesn't have a default implementation. This is >>> because, if >>> >> >>> >> Yes, *at the moment of writing* the type's code there could be no >>> default >>> >> implementation for protocol requirement. But, *at the moment of >>> >> compilation* such default implementation could appear. >>> >> >>> >> Let's discuss such scenario in case we'll take your suggestion: >>> >> >>> >> You got SomeClass.swift file, 3rd party file you don't want to change >>> or >>> >> changes are not allowed. Content: >>> >> >>> >> public protocol SomeProtocol { >>> >> func foo() >>> >> } >>> >> >>> >> public class SomeClass : SomeProtocol { >>> >> func foo() {...} // no default implementation *at the moment of >>> writing*, >>> >> no need in `overload` >>> >> } >>> >> >>> >> Now, you adds SomeClass.swift file to your project and in some *other* >>> >> file you write: >>> >> >>> >> extension SomeProtocol { >>> >> func foo() {...} >>> >> } >>> >> >>> >> As you see, you don't control the SomeClass.swift but you suggest in >>> this >>> >> case SomeClass.foo() should be defined with `override`. >>> >> >>> >> With 'implement' SomeClass.foo() will be marked initially and will >>> save >>> >> us if protocol's requirement PLUS default implementation changed. >>> > >>> > Requiring the ‘implement’ keyword can help us even if no default >>> > implementation is involved. Consider: >>> > >>> > protocol P { >>> > func foo() -> [String : Any] >>> > } >>> > >>> > struct S : P { >>> > func foo() -> [String : String] { return [:] } >>> > } >>> > >>> > We will get an error here that S does not conform to P. However, this >>> is >>> > not the correct error, since S in fact *tries* to conform to P, but it >>> has >>> > a mistake in a method signature. This misleads us as to the true >>> nature of >>> > the problem, and if S has enough members in it that we fail to spot the >>> > existing foo(), we might solve the problem by reimplementing foo(), and >>> > leaving the original foo() as dangling dead code. Having an ‘implement’ >>> > keyword on the existing foo() function would change the compiler error >>> to >>> > let us know that we have an existing foo() that is incorrectly >>> declared. >>> > >>> > In addition, ‘implement’ can help us when the declaration in question >>> *is* >>> > the default implementation: >>> > >>> > protocol P { >>> > func foo() -> [String : Any] >>> > } >>> > >>> > extension P { >>> > implement func foo() -> [String : String] { return [:] } >>> > } >>> > >>> > Here we will get an error with the proposed ‘implement’ keyword, >>> because >>> > foo() does not have a signature matching anything in the protocol, >>> whereas >>> > without ‘implement’ we would happily and silently generate a useless >>> > dangling function that would never be used, and then pass the buck to >>> the >>> > concrete type that implements P: >>> > >>> > protocol P { >>> > func foo() -> [String : Any] >>> > } >>> > >>> > extension P { >>> > func foo() -> [String : String] { return [:] } // The error is here: >>> > } >>> > >>> > struct S : P {} // But it gets reported here. >>> > >>> > Charles >>> > >>> _______________________________________________ >>> swift-evolution mailing list >>> swift-evolution@swift.org >>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org >> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution > > > > I agree that a new keyword is unwanted. Conforming to protocols is quite a > common thing, so you want it to be easy to remember. > > I think the best way is to prefix the member name with the protocol, e.g: > > protocol MyProto { > var aVariable : Int > func aFunction() > } > class MyClass : MyProto { > var MyProto.aVariable : Int > func MyProto.aFunction() { … } > } > > This is consistent with how we refer to other members of types (e.g. > “extension MyClass.MyInternalClass”). It will be easy for autocompletion to > provide good suggestions, too. > As I see it, the only problem is what if `MyClass` wants its own function > called `aFunction()`? What if the same name satisfies 2 protocols, which do > you write? > > The way to solve all of the problems in a consistent way is to make the > function actually called “MyProto.aFunction”, and for it to be a separate > function from plain “aFunction()” or from “SomeotherProto.aFunction”. > > I believe it is crucial to protocols that we can do this. Maybe I have > some complex data structure and it has its own API, but I want people to be > able to view it as a Collection. By conforming to Collection, I reserve > lots of keywords and indexing operations which I now can’t use in my own > API. Maybe I’m just providing Collection as a convenience to work with > generic algorithms, but my own API has more efficient semantics for some > operations. We’re relegated to using less-obvious and legible names in > order to avoid conflicts. > > We have a way to work around this, which String uses - create a struct > which references your object and calls internal methods such as > “_collection_count” so you can have separate interfaces. This adds up to > quite a lot of boilerplate and maintenance overhead. > > > Also to add here: you’re basically implementing what I’m proposing > manually if you do this; only you don’t get language/compiler support. > String basically does this - it shares StringCore with UTF8View and > defines some internal functions to support it. > > The String views could then be made in to protocols on String, turning > “UTF8View” in to “UTF8Representable”, and opening up algorithms which can > work on generic sequences of UTF8 bytes. I think that’s pretty cool, and > could open up better integration with other types which are (for example) > UTF8Representable — for example a stream of UTF8 bytes (depending on how > flexible implementation allows us to make the protocol). > > > I don’t agree that Protocol conformances are kind-of incidental, as others > here have written. This isn’t like Objective-C where anything that has the > correctly-named methods conforms. Protocol conformances are completely > explicit, and in fact we have empty protocols (“marker protocols”) for > exactly that purpose. I think it is consistent that we make every member of > a conformance specify which protocol it belongs to, and to have its name > scoped to that protocol. > > Karl > > > CC-ing Dave A, to understand better if this fits with the vision of > protocols > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution >
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution