<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Hi Kevin,<div class=""><br class=""></div><div class="">Thanks for taking time to look at the proposal.</div><div class=""><br class=""></div><div class="">The technique you show here is not bad, but it has several deficiencies IMO which are addressed by the solution in the proposal.</div><div class=""><br class=""></div><div class="">1. Forwarding should be an implementation detail, not exposed as it is with this method.<br class="">2. As such, the getter for the forwardee is visible. &nbsp;The forwardee is an implementation detail that should not be visible in most cases.<br class="">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.<br class="">4. You can't forward to a type that doesn't conform to the protocol. &nbsp;This is particularly important for existential forwardees (at least until they conform to their protocol).<br class="">5. A type that can't conform to the protocol can't forward an implementation of the members of the protocol. &nbsp;Specifically, non-final classes cannot automatically forward a group of methods to an implementer.<br class="">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?<br class=""><br class=""></div><div class="">You may be right that many protocols are not amenable to forwarding. &nbsp;The motivation for this proposal is that it enables delegation-based designs to be implemented succinctly. &nbsp;In that use case the protocols will be designed alongside concrete implementations and types that forward to them. &nbsp;A secondary motivation for this proposal is to lay a foundation for a newtype feature. &nbsp;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.</div><div class=""><br class=""></div><div class="">I hope these points might be enough to convince you that it is worth a closer look.</div><div class=""><br class=""></div><div class="">Matthew</div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Dec 29, 2015, at 2:06 PM, Kevin Ballard via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class="">


<title class=""></title>

<div class=""><div class="">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).<br class=""></div>
<div class="">&nbsp;</div>
<div class="">For example, if I want to automatically forward SequenceType to a member, I can do something like<br class=""></div>
<div class="">&nbsp;</div>
<div class=""><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">protocol</span> SequenceTypeForwarder : <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">SequenceType</span> {</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">typealias</span> ForwardedSequenceType : SequenceType</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">var</span> forwardedSequence : <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">ForwardedSequenceType</span> { <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">get</span> }</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">}</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(112, 61, 170);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">extension</span><span style="" class=""> </span>SequenceTypeForwarder<span style="" class=""> {</span></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(112, 61, 170);" class=""><span style="" class="">&nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span><span style="" class=""> generate() -&gt; </span>ForwardedSequenceType<span style="" class="">.</span>Generator<span style="" class=""> {</span></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> forwardedSequence.generate()</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; }</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span> underestimateCount() -&gt; <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Int</span> {</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> forwardedSequence.underestimateCount()</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; }</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span> map&lt;T&gt;(<span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">@noescape</span> transform: (ForwardedSequenceType.Generator.Element) <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">throws</span> -&gt; T) <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">rethrows</span> -&gt; [<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">T</span>] {</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">try</span> forwardedSequence.map(transform)</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; }</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span> filter(<span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">@noescape</span> includeElement: (ForwardedSequenceType.Generator.Element) <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">throws</span> -&gt; Bool) <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">rethrows</span> -&gt; [<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">ForwardedSequenceType</span>.<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Generator</span>.<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Element</span>] {</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">try</span> forwardedSequence.filter(includeElement)</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; }</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span> forEach(<span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">@noescape</span> body: (ForwardedSequenceType.Generator.Element) <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">throws</span> -&gt; Void) <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">rethrows</span> {</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">try</span> forwardedSequence.forEach(body)</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; }</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(112, 61, 170);" class=""><span style="" class="">&nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span><span style="" class=""> dropFirst(n: </span>Int<span style="" class="">) -&gt; </span>ForwardedSequenceType<span style="" class="">.</span>SubSequence<span style="" class=""> {</span></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> forwardedSequence.dropFirst(n)</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; }</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(112, 61, 170);" class=""><span style="" class="">&nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span><span style="" class=""> dropLast(n: </span>Int<span style="" class="">) -&gt; </span>ForwardedSequenceType<span style="" class="">.</span>SubSequence<span style="" class=""> {</span></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> forwardedSequence.dropLast(n)</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; }</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(112, 61, 170);" class=""><span style="" class="">&nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span><span style="" class=""> prefix(maxLength: </span>Int<span style="" class="">) -&gt; </span>ForwardedSequenceType<span style="" class="">.</span>SubSequence<span style="" class=""> {</span></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> forwardedSequence.prefix(maxLength)</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; }</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(112, 61, 170);" class=""><span style="" class="">&nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span><span style="" class=""> suffix(maxLength: </span>Int<span style="" class="">) -&gt; </span>ForwardedSequenceType<span style="" class="">.</span>SubSequence<span style="" class=""> {</span></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> forwardedSequence.suffix(maxLength)</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; }</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span> split(maxSplit: Int, allowEmptySlices: Bool, <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">@noescape</span> isSeparator: (ForwardedSequenceType.Generator.Element) <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">throws</span> -&gt; Bool) <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">rethrows</span> -&gt; [<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">ForwardedSequenceType</span>.<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">SubSequence</span>] {</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">try</span> forwardedSequence.split(maxSplit, allowEmptySlices: allowEmptySlices, isSeparator: isSeparator)</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; }</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">}</div></div>
<div class="">&nbsp;</div>
<div class="">With this protocol declared, I can then say something like<br class=""></div>
<div class="">&nbsp;</div>
<div class=""><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">struct</span> Foo {</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">var</span> ary: [<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Int</span>]</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">}</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(112, 61, 170);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">extension</span><span style="" class=""> </span>Foo<span style="" class=""> : </span>SequenceTypeForwarder<span style="" class=""> {</span></div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">var</span> forwardedSequence: [<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Int</span>] { <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> ary }</div><div style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">}</div></div>
<div class="">&nbsp;</div>
<div class="">and my struct Foo now automatically implements SequenceType by forwarding to its variable `ary`.<br class=""></div>
<div class="">&nbsp;</div>
<div class="">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.<br class=""></div>
<div class="">&nbsp;</div>
<div class="">-Kevin Ballard</div>

<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=eLFMrKDT8iBxZ-2Fbnk-2BZqvSchNN-2FvYXdceA0T7VxwkAf1zYqA0eDscHbH9SDyWjzGWFLihZnsozyy4wMWC59L5khASYp0oY91FEdE-2FmETcJiF2Oz7960pAIQr6EOvmBGKMfc-2F95miMje0LanBSl8uXLyFfMm0fT4aT-2B7tHWJD0MFgOQ-2FemPcod5k3-2FuNgZZeTpd82ANpTsXqPrG7zMD327Q8SCaforlMhzBTuFTx-2BIAI-3D" alt="" width="1" height="1" border="0" style="height:1px !important;width:1px !important;border-width:0 !important;margin-top:0 !important;margin-bottom:0 !important;margin-right:0 !important;margin-left:0 !important;padding-top:0 !important;padding-bottom:0 !important;padding-right:0 !important;padding-left:0 !important;" class="">
</div>


_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></div></body></html>