> 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