> On Dec 31, 2015, at 9:47 AM, Matthew Johnson <matt...@anandabits.com> wrote:
> 
>> 
>> On Dec 31, 2015, at 11:18 AM, Dave Abrahams <dabrah...@apple.com 
>> <mailto:dabrah...@apple.com>> wrote:
>> 
>>> 
>>> On Dec 31, 2015, at 9:01 AM, Matthew Johnson <matt...@anandabits.com 
>>> <mailto:matt...@anandabits.com>> wrote:
>>> 
>>> 
>>> 
>>> Sent from my iPad
>>> 
>>> On Dec 31, 2015, at 10:09 AM, Dave Abrahams <dabrah...@apple.com 
>>> <mailto:dabrah...@apple.com>> wrote:
>>> 
>>>> 
>>>> -Dave
>>>> 
>>>>> On Dec 31, 2015, at 7:33 AM, Matthew Johnson via swift-evolution 
>>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>>>> 
>>>>>> 
>>>>>> On Dec 31, 2015, at 5:04 AM, Tino Heth <2...@gmx.de 
>>>>>> <mailto:2...@gmx.de>> wrote:
>>>>>> 
>>>>>> 
>>>>>>> I don’t want this thread to get distracted with memberwise 
>>>>>>> initialization
>>>>>> Makes sense in general, but Kotlin solves those problems as a whole, and 
>>>>>> the major benefit of their approach is that everything fits together 
>>>>>> really fine.
>>>>>> But I'll skip everything that is not related to forwarding.
>>>>>> 
>>>>>>> One approach I considered would look like this:
>>>>>>> 
>>>>>>> class Forwarder: P {
>>>>>>>    // I didn’t like `implements` but didn’t have a better idea before I 
>>>>>>> abandoned this approach
>>>>>>>    var forwardee: Forwardee implements P 
>>>>>>> }
>>>>>> Honestly, I'm can't see the value this discarded variant has for this 
>>>>>> discussion… you have to pit your proposal against Kotlin if you really 
>>>>>> want to convince anyone of its superiority.
>>>>>> 
>>>>>>> With the memberwise initialization proposal you also have the 
>>>>>>> initializer synthesized automatically.  The only thing it doesn’t do 
>>>>>>> that your Kotlin example does is automatically declare conformance.  
>>>>>>> This was an intentional design decision because it allows for 
>>>>>>> additional expressivity.  This is addressed in the alternatives 
>>>>>>> considered section of the proposal.  
>>>>>> Can you be more precise? Kotlin clearly states what a class is doing in 
>>>>>> its first line, with all expressivity that is necessary by practical 
>>>>>> means.
>>>>> 
>>>>> What I mean is this.  In the example you gave and the syntax Kotlin uses:
>>>>> 
>>>>> classs Forwarder(forwardee: Forwardee): P by forwardee {}
>>>>> 
>>>>> Forwarding is coupled to protocol conformance.  This means I cannot use 
>>>>> forwarding without conforming to the protocol that is forwarded.  
>>>>> 
>>>>> Here is a quick example using the syntax of my proposal to demonstrate 
>>>>> the difference:
>>>>> 
>>>>> class Forwarder {
>>>>>   let forwardee: Forwardee
>>>>>   forward P to forwardee
>>>>> }
>>>>> 
>>>>> vs
>>>>> 
>>>>> class Forwarder: P {
>>>>>   let forwardee: Forwardee
>>>>>   forward P to forwardee
>>>>> }
>>>>> 
>>>>> In the first example Forwarder does not conform to P.  Forwarding is only 
>>>>> used to synthesize the members of P.  I am greatly expanding the 
>>>>> motivation section of the proposal and will have examples showing where 
>>>>> this is what you want.  The lazy collections section I posted last night 
>>>>> includes the first examples where this is the case.
>>>>> 
>>>>> In the second example here Forwarder does conform to P.  The author of 
>>>>> Forwarder has the flexibility to specify whether conformance is desired 
>>>>> or not.
>>>> 
>>>> There are ways to handle that, including factoring the APIs of interest 
>>>> out of P and into a private protocol Q, then declaring the Forwardee’s 
>>>> conformance to Q.  Now, there’s an expressivity problem with our current 
>>>> access control system that you can’t use an internal or private protocol 
>>>> to provide public API, but that should be fixed separately.
>>> 
>>> I'm not sure where Q comes into play in this specific example.  The idea 
>>> here is that forwarding implementations of all members of P are synthesized 
>>> by the forward declaration.  It is left up to Forwarder to decide whether 
>>> or not to declare actual conformance to P.  I am also confused by "then 
>>> declaring the Forwardee’s conformance to Q" because we are discussing 
>>> Forwarder's conformance here, not Forwardee’s.
>> 
>> Presumably both ends of the forwarding arrangement would have to conform to 
>> the same protocol, no?
> 
> No.  This is addressed in the proposal and the lazy collections motivating 
> example I replied with last night.  I don’t think it’s a good idea to require 
> this.
> 
> The forwardee needs to implement the members of the protocol but does not 
> need to conform.  The forwarder will receive forwarding implementations of 
> the members, but again does not need to declare conformance.  Forwarding is 
> orthogonal to conformance, just as it is today when you manually write 
> forwarding members today.
> 
>> 
>>> What do you have in mind when you mention using a private or internal 
>>> protocol to provide public API?  It sounds like that might be interesting 
>>> but I'm having trouble imagining what the syntax would look like and 
>>> exactly how it would work.  Is this something that is planned?  
>> 
>> Not planned, but desired.
>> 
>>> What might it look like?
>> 
>> Details need to be worked out.  One thing we were doing for a while in the 
>> stdlib, before the rules got tightened and made it impossible, was
>> 
>> struct X : PublicProtocol, PrivateProtocol {
>>    ...
>> }
>> 
>> extension PublicProtocol where Self : PrivateProtocol {
>>    // API that uses only PublicProtocol in its implementation here
>> }
> 
> Presumably you implement public API here where members of PrivateProtocol can 
> be accessed?  This would address the problem of leaking implementation 
> details when adding default forwarding implementations so it is definitely 
> better than current state.
> 
>> 
>>> In any case, I don't see why that is related to requiring a Forwarder to 
>>> conform to the forwarded protocol.  There doesn't appear to me to be a good 
>>> reason to require that and there are reasons not to require it.  Protocols 
>>> enable and drive the forwarding member synthesis mechanism but that 
>>> mechanism doesn't need to require or provide conformance.  It is a third 
>>> major way to use protocols in addition to generic constraints and 
>>> existential types.
>> 
>> Of course I could be wrong, but my instincts tell me that is an unneeded 
>> dimension of complexity, which is why I am resisting it.  The 
>> generic/existential duality is already problematic in some ways, IMO.
> 
> I don’t really understand what is complex about it.  Can you elaborate on why 
> you think it introduces complexity?  The idea seems pretty simple to me - if 
> you can write a forwarding implementation that compiles and works the 
> compiler should be able to synthesize it for you.  I don’t see any reason to 
> disallow that.  
> 
> Is your concern that we may not be able to support forwarding of every 
> protocol someone might come up with and there would be confusion around what 
> protocols are eligible for forwarding and which aren’t (similar to the 
> current confusion around which protocols can be used as existentials and 
> which can’t)?

No, it just feels like an ad-hoc use of protocols to use their APIs as 
constraints without creating a conformance.

> Isn’t the primary problem with generic / existential the fact that 
> existentials are pretty limited currently?  This is an unfortunate limitation 
> and my understanding is that there is a desire to lift at least some parts of 
> this limitation eventually, whether that starts to happen in Swift 3 or is a 
> feature that comes later. 
> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151214/002850.html
>  
> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151214/002850.html>
Yes, there are plans to address this (and I’m looking forward to that!), but I 
think the difference is still going to be there and when to use one or the 
other is still going to remain a point of confusion.

> One specific problem with requiring conformance is that forwarding to 
> existentials would not be straightforward because they do not conform to 
> their protocol.  Obviously this is a limitation that should be lifted 
> eventually but it isn’t clear when that might happen.
> 
>> 
>>> 
>>>> 
>>>>> 
>>>>>> 
>>>>>>> Another difference that is maybe subtle but I think important is that 
>>>>>>> with the approach I considered forwarding is declared in the body of a 
>>>>>>> type or extension which emphasizes the fact that forwarding is an 
>>>>>>> implementation detail, not something users of the type should be 
>>>>>>> concerned with.
>>>>>> But what is the benefit of this emphasis? No solution requires to make 
>>>>>> the details visible in the public interface, and the ability to bury an 
>>>>>> important thing like protocol conformance somewhere in the class 
>>>>>> implementation is no advantage for me.
>>>>> 
>>>>> Protocol conformance is not buried in the implementation in my solution.  
>>>>> I hope the previous example makes that clear.  What is buried in the 
>>>>> implementation is the forwarding declaration which causes the compiler to 
>>>>> synthesize forwarding member implementations.  This synthesis is an 
>>>>> implementation detail and should not be visible outside the 
>>>>> implementation.
>>>>> 
>>>>>> 
>>>>>>> This approach was abandoned as it leads to problems in expressivity and 
>>>>>>> clarity.  Please see alternatives considered for an elaboration of 
>>>>>>> that.  This is especially true with the new approach to handling Self 
>>>>>>> values that Brent suggested.  That approach requires additional syntax 
>>>>>>> around the forwarding declaration, but adds both clarity and 
>>>>>>> expressiveness.
>>>>>> I think there is little need to worry about expressiveness for a feature 
>>>>>> that most potential users will probably never utilize in real code — and 
>>>>>> I don't think options like not conforming to a protocol that is 
>>>>>> forwarded is a big win here. It looks to me like you are optimizing for 
>>>>>> very uncommon cases, and sacrificing ease of use in the situations that 
>>>>>> are the most common by far.
>>>>> 
>>>>> Like I stated, I am working on adding several examples of how this 
>>>>> feature can be used in real code.  Please have a look at the lazy 
>>>>> collections example I shared last night.  This example, as well as at 
>>>>> least one other coming examples take advantage of the ability to use 
>>>>> forwarding without requiring conformance.
>>>>> 
>>>>> As with the memberwise initialization proposal, the syntax you would like 
>>>>> to see can easily be added as syntactic sugar on top of the current 
>>>>> proposal.  I would not support that as I do not like the syntax Kotlin 
>>>>> uses for reasons already stated, but that shouldn’t stop you from 
>>>>> pursuing a proposal for it.  Maybe a lot of people would agree with you 
>>>>> and it would be accepted.
>>>>> 
>>>>> Matthew
>>>>> 
>>>>>> 
>>>>>>> It appears to me that you value conciseness very highly.  I do value 
>>>>>>> conciseness but I also value safety, clarity, and expressiveness.  
>>>>>> No, I value elegance and simplicity  — they often lead to clarity and 
>>>>>> safety.
>>>>>> 
>>>>>>>> Why not simply make this feature syntactic sugar and just 
>>>>>>>> auto-generate the forwarding methods?
>>>>>>> 
>>>>>>> That is exactly what this proposal does.  Why do you feel it is not 
>>>>>>> doing that?
>>>>>> you're right, guess I mixed up the proposal with something else; so at 
>>>>>> least we agree on how it should work ;-)
>>>>>> 
>>>>>> I'm not saying Swift has to copy another language, but I doubt that 
>>>>>> anyone who knows Kotlin would actually consider to drop their solution 
>>>>>> in favor of what is currently discussed...
>>>>>> 
>>>>>> Tino
>>>>>> 
>>>>> 
>>>>>  _______________________________________________
>>>>> 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>
>> 
>> -Dave

-Dave

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

Reply via email to