Sorry if that sounds a little bit rude, I’ve been switching between English and 
German a lot and the way you speak in one language can come across wrong in 
another!

> On 21 Sep 2016, at 01:58, Karl <raziel.im+swift-...@gmail.com> wrote:
> 
> I’ve explained it so many times, do you really not understand it?
> 
> Basically, protocols are explicit things. They are **not** things that you 
> just “discover” about types at all. We have protocols with no members 
> (“marker protocols”) which are basically used to tag certain types with no 
> other guarantees. That is the important difference between protocols in Swift 
> and in Objective-C. Even if you have implementations for every requirement, 
> if you never explicitly declared conformance you don’t conform. Period.
> 
> However, the requirements themselves don’t need to be explicitly marked-up. 
> They just get automatically assigned by the compiler; maybe my property named 
> “count” doesn’t mean the same thing as Collection’s “count”?
> 
> I’ve written a lot trying to explain this; please tell me what you don’t 
> understand. To summarise (again):
> 
> - Members which satisfy a protocol requirement will have to be explicit about 
> which protocol they belong to
> ——> They will no longer be automatically assigned as the witness for a 
> protocol requirement
> 
> - Members which satisfy a protocol requirement will have the protocol name in 
> their symbolic names (e.g. MyType.someFunction() —> 
> MyType.AProtocol.someFunction())
> ——> this will allow the same type to conform to protocols with overlapping 
> names, free protocol designers from naming constraints, and reduce the need 
> for “helper structs” to represent alternate views of the same data.
> ——> Extensions which declare conformance have to satisfy all of their 
> requirements explicitly - by implementing, forwarding to other functions, 
> stored properties or other objects. We can have a shorthand to make this easy.
> 
> IMO, we definitely need to solve the overlapping naming problem. If we 
> explicitly assign protocol methods to protocols (as the thread was originally 
> about), this falls out of it.
> 
> 
>> On 21 Sep 2016, at 01:25, Xiaodi Wu <xiaodi...@gmail.com 
>> <mailto:xiaodi...@gmail.com>> wrote:
>> 
>> This was the conversation we were having in the other thread. Perhaps I'm 
>> still not understanding something, but I'm not convinced that this feature 
>> is an improvement.
>> 
>> Currently, protocols represent a declaration that you have discovered that 
>> your type has certain semantics and guarantees a certain API, and you 
>> declare that fulfillment "by name only," just as you invoke members "by name 
>> only"; unintentional failure to fulfill the contract is a compile-time 
>> error. The status quo is precisely my idea of what protocols should be. What 
>> are the two ideas you have about them?
>> On Tue, Sep 20, 2016 at 18:02 Karl <razie...@gmail.com 
>> <mailto:razie...@gmail.com>> wrote:
>> I’m using String as an example of where this issue of conformance conflicts 
>> crops up in the standard library. Ideally, String (or any data type) should 
>> be able to conform to protocols whose requirements have conflicting names.
>> Currently, in order to work around this limitation, you have to delegate the 
>> conformance to a supporting type. This is more complicated to write and 
>> maintain, and pollutes your internal API. String gives us an example of 
>> this, but it’s not the worst example.
>> It basically implements what I’m talking about anyway, but manually via a 
>> supporting type instead of directly inside the data-type (String). As an ABI 
>> consideration, we should scope all protocol members to their protocols. This 
>> would resolve all naming conflicts.
>> 
>> I can’t understand how anybody would argue for the status quo - we’re 
>> currently in-between two ideas of what protocols should be - they are 
>> explicit but their conformances are resolved by name only and can overlap 
>> without warning.
>> 
>>> On 21 Sep 2016, at 00:48, Xiaodi Wu <xiaodi...@gmail.com 
>>> <mailto:xiaodi...@gmail.com>> wrote:
>>> 
>>> Sorry, I'm still not sure I understand what you're getting at about this. 
>>> How would String conforming to Collection multiple times simplify or 
>>> improve the implementation of String? Or are you arguing it would be better 
>>> for users of String? If so, how?
>>> 
>>> On Tue, Sep 20, 2016 at 17:26 Karl <razie...@gmail.com 
>>> <mailto:razie...@gmail.com>> wrote:
>>> I’m not saying vital support is missing, just that it is more awkward. 
>>> String doesn’t conform to collection, String.UTF8View does; so if you 
>>> change some implementation detail (in StringCore, because that’s where they 
>>> live for String), you get the error popping up somewhere other than the 
>>> place you just changed. That’s what I mean when I say “language support”. 
>>> If you do what StringCore does, and you’re changing stuff which is 
>>> ultimately going to be used to conform to, say, Collection, you have to 
>>> build distance between the implementation and the (only) conformance it is 
>>> used for, and it’s less optimal.
>>> 
>>> Let’s say I have an object MyComplexDataType, it implements 
>>> “InternalStructureView” and “Collection”:
>>> 
>>> ```
>>> protocol InternalStructureView {
>>>     associatedtype Index
>>>     var count : Int { get } // whatever, just some stuff that will cause a 
>>> name conflict
>>>     func doInternalMagic(at: Index)
>>> }
>>> 
>>> struct MyComplexDataType {
>>>     var __collection_count : Int {
>>>         // This is quite a complex operation which we’d rather leave inside 
>>> the type, otherwise we’d need to expose a bunch of implementation details 
>>> internally
>>>     }
>>>    var __internal_count : Int {
>>>        // Again, best left here
>>>    }
>>> 
>>>    struct CollectionView  : Collection {
>>>        init(parent: MyComplexDataType) { … }
>>>         var count { return parent.__collection_count }
>>>         // ...etc
>>>    }
>>> 
>>>   struct InternalStructure : InternalStructureView {
>>>       init(parent: MyComplexDataType) { … }
>>>       var count { return parent.__internal_count }
>>>       // ...etc
>>>   }
>>> 
>>>   var collection : CollectionView { return CollectionView(self) }
>>>   var internalStructure : InternalStructure { return 
>>> InternalStructure(self) }
>>> }
>>> ```
>>> 
>>> This is basically what String does (except that it wants to conform to 
>>> Collection multiple times with different indexes and results). It’s a lot 
>>> of work to maintain, especially if you have evolving protocols that are 
>>> conformed to in several places.
>>> We should have a better solution. We should be able to define:
>>> 
>>> “protocol UTF8Collection : Collection {}
>>>  protocol UTF16Collection : Collection {}”
>>> 
>>> and have String conform to both of them at the same time. At the same time, 
>>> since we’re now being explicit about which protocol requirement is 
>>> satisfied where - we should also be able to delegate our conformance, 
>>> telling the compiler to dispatch any unimplemented methods to another 
>>> object. For example, lets say you want to wrap a Collection and observe 
>>> mutations to it; you might override replaceSubrange(), but every other 
>>> method (such as count, index(after:)… all the rest) is just a forwarding 
>>> function.
>>> 
>>> Interestingly, we could do this safely (from a code legibility perspective) 
>>> if we say that every scope which adds a conformance must completely satisfy 
>>> its requirements, which we would more reasonably be able to require if we 
>>> made this change (so your internal functions can still be wherever you 
>>> like, but they won’t automatically satisfy a protocol requirement if they 
>>> happen to have the same name). Then we could reasonably say that if you add 
>>> an extension which adds a conformance to, say, Collection, you have to tell 
>>> us where to find every one of its requirements. That’s where we could put 
>>> the forwarding syntax for retroactive modelling. Stored properties can’t be 
>>> defined in extensions, so if you want to back an implementation with one, 
>>> you’ll need to make its conformance explicit in the main body (or we loosen 
>>> that to at least extensions in the same file).
>>> 
>>> ```
>>> // generates thunks to members of this extension in the base type; 
>>> // so MyComplexDataType.count —> MyComplexDataType.InternalStructure.count,
>>> // to account for conformance being added in later version. Can also be 
>>> used for renamed protocols, and be tagged on individual members.
>>> 
>>> @makeAvailable(as: _)
>>> extension MyComplexDataType : InternalStructure {
>>> 
>>>    typealias Index = InternalIndexType
>>>     var count : Int {
>>>         // We have access to all of the private members because we’re 
>>> inside MyComplexDataType
>>>         // No need to pollute internal API with conformance implementation 
>>> details.
>>>         // Also, we get errors about non-conformance where we want them — 
>>> where the implementation is.
>>>     }
>>>     func doInternalMagic(at: Index) {
>>>        ...
>>>     }
>>> }
>>> ```
>>> 
>>>> On 20 Sep 2016, at 23:46, Xiaodi Wu <xiaodi...@gmail.com 
>>>> <mailto:xiaodi...@gmail.com>> wrote:
>>>> 
>>>> 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 <mailto:swift-evolution@swift.org>> wrote:
>>>>> On 20 Sep 2016, at 23:28, Karl <raziel.im+swift-...@gmail.com 
>>>>> <mailto:raziel.im+swift-...@gmail.com>> wrote:
>>>>> 
>>>>> 
>>>>>> On 20 Sep 2016, at 18:43, Nevin Brackett-Rozinsky via swift-evolution 
>>>>>> <swift-evolution@swift.org <mailto: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 <mailto: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 <mailto: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> 
>>>>>> >> <mailto: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 <mailto:swift-evolution@swift.org>
>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>>> 
>>>>>> _______________________________________________
>>>>>> swift-evolution mailing list
>>>>>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>>> 
>>>>>> 
>>>>>> _______________________________________________
>>>>>> swift-evolution mailing list
>>>>>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>>>> <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 <mailto:swift-evolution@swift.org>
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>> 
>> 
> 

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to