> On Dec 29, 2015, at 1:24 PM, Matthew Johnson via swift-evolution 
> <[email protected]> wrote:
> 
> Hi Kevin,
> 
> Thanks for taking time to look at the proposal.
> 
> The technique you show here is not bad, but it has several deficiencies IMO 
> which are addressed by the solution in the proposal.
> 
> 1. Forwarding should be an implementation detail, not exposed as it is with 
> this method.

This could theoretically be managed by access control on protocol conformances:

public struct Foo: internal SequenceTypeForwarder, public SequenceType { ... }

though that's even more boilerplatey, and makes it easy to accidentally expose 
more API than you intended to.

-Joe

> 2. As such, the getter for the forwardee is visible.  The forwardee is an 
> implementation detail that should not be visible in most cases.
> 3. There is no way to specify access control for the synthesized methods and 
> if there were it would be coupled to the access control of the conformance.
> 4. You can't forward to a type that doesn't conform to the protocol.  This is 
> particularly important for existential forwardees (at least until they 
> conform to their protocol).
> 5. A type that can't conform to the protocol can't forward an implementation 
> of the members of the protocol.  Specifically, non-final classes cannot 
> automatically forward a group of methods to an implementer.
> 6. This solution does not lay the foundation for a newtype feature. It would 
> be possible to have a specialized newtype feature, but why not build it on 
> top of a more general forwarding feature?
> 
> You may be right that many protocols are not amenable to forwarding.  The 
> motivation for this proposal is that it enables delegation-based designs to 
> be implemented succinctly.  In that use case the protocols will be designed 
> alongside concrete implementations and types that forward to them.  A 
> secondary motivation for this proposal is to lay a foundation for a newtype 
> feature.  In that case the protocols to be forwarded would be specifically 
> designed to represent the portion of the interface of the wrapped type which 
> should be visible to users of the newtype.
> 
> I hope these points might be enough to convince you that it is worth a closer 
> look.
> 
> Matthew
> 
>> On Dec 29, 2015, at 2:06 PM, Kevin Ballard via swift-evolution 
>> <[email protected] <mailto:[email protected]>> wrote:
>> 
>> I briefly skimmed your proposal, so I apologize if you already addressed 
>> this, but it occurs to me that we could support automatic protocol 
>> forwarding today on a per-protocol basis simply by declaring a separate 
>> protocol that provides default implementations doing the forwarding. 
>> Handling of Self return types can then be done by adding a required 
>> initializer (or just not implementing that method, so the concrete type is 
>> forced to deal with it even though everything else is forwarded).
>>  
>> For example, if I want to automatically forward SequenceType to a member, I 
>> can do something like
>>  
>> protocol SequenceTypeForwarder : SequenceType {
>>     typealias ForwardedSequenceType : SequenceType
>> 
>>     var forwardedSequence : ForwardedSequenceType { get }
>> }
>> 
>> extension SequenceTypeForwarder {
>>     func generate() -> ForwardedSequenceType.Generator {
>>         return forwardedSequence.generate()
>>     }
>> 
>>     func underestimateCount() -> Int {
>>         return forwardedSequence.underestimateCount()
>>     }
>> 
>>     func map<T>(@noescape transform: 
>> (ForwardedSequenceType.Generator.Element) throws -> T) rethrows -> [T] {
>>         return try forwardedSequence.map(transform)
>>     }
>> 
>>     func filter(@noescape includeElement: 
>> (ForwardedSequenceType.Generator.Element) throws -> Bool) rethrows -> 
>> [ForwardedSequenceType.Generator.Element] {
>>         return try forwardedSequence.filter(includeElement)
>>     }
>> 
>>     func forEach(@noescape body: (ForwardedSequenceType.Generator.Element) 
>> throws -> Void) rethrows {
>>         return try forwardedSequence.forEach(body)
>>     }
>> 
>>     func dropFirst(n: Int) -> ForwardedSequenceType.SubSequence {
>>         return forwardedSequence.dropFirst(n)
>>     }
>> 
>>     func dropLast(n: Int) -> ForwardedSequenceType.SubSequence {
>>         return forwardedSequence.dropLast(n)
>>     }
>> 
>>     func prefix(maxLength: Int) -> ForwardedSequenceType.SubSequence {
>>         return forwardedSequence.prefix(maxLength)
>>     }
>> 
>>     func suffix(maxLength: Int) -> ForwardedSequenceType.SubSequence {
>>         return forwardedSequence.suffix(maxLength)
>>     }
>> 
>>     func split(maxSplit: Int, allowEmptySlices: Bool, @noescape isSeparator: 
>> (ForwardedSequenceType.Generator.Element) throws -> Bool) rethrows -> 
>> [ForwardedSequenceType.SubSequence] {
>>         return try forwardedSequence.split(maxSplit, allowEmptySlices: 
>> allowEmptySlices, isSeparator: isSeparator)
>>     }
>> }
>>  
>> With this protocol declared, I can then say something like
>>  
>> struct Foo {
>>     var ary: [Int]
>> }
>> 
>> extension Foo : SequenceTypeForwarder {
>>     var forwardedSequence: [Int] { return ary }
>> }
>>  
>> and my struct Foo now automatically implements SequenceType by forwarding to 
>> its variable `ary`.
>>  
>> The downside to this is it needs to be manually declared for each protocol. 
>> But I wager that most protocols actually aren't really amenable to 
>> forwarding anyway.
>>  
>> -Kevin Ballard
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> 
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to