<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">I would also like to see language support for concise forwarding. &nbsp;It gives composition a conciseness that approaches inheritance which makes it much more pragmatic than it currently is. &nbsp;This is a huge win IMO.</div><div class=""><br class=""></div><div class="">Forwarding protocol implementations would provide the most value, but forwarding individual methods (whether part of a protocol implementation or not) may also be useful. &nbsp;Maybe a single mechanism could accomplish both?</div><div class=""><br class=""></div><div class="">When forwarding protocols, it would be ideal to also allow the forwarding class to explicitly implement specific methods of the protocol while the rest are forwarded automatically.</div><div class=""><br class=""></div><div class="">One detail that definitely needs to be addressed is how a protocol with members using Self would be handled, especially when Self is used as a return value. &nbsp;I’m not sure if these methods could be forwarded automatically or not. &nbsp;David, do you have any ideas as to how this would be handled?</div><div class=""><br class=""></div><div class="">Another detail that needs to be addressed is how protocols with associated types are forwarded. &nbsp;I think this would be more straightforward but the details need to be written up to be sure.</div><div class=""><br class=""></div><div class="">Syntactically, I think it would make most sense to specify forwarding along side the member declaration rather than in a separate declaration and should support multiple protocols to be forwarded to the same member in the same declaration. &nbsp;Something like this:</div><div class=""><br class=""></div><div class=""><span style="font-family: Menlo;" class="">class&nbsp;Cluster: _Cluster, Foo, Bar {</span><font color="#5856d6" face="Menlo" class=""><br class="">&nbsp; &nbsp; // Ideally the member could have any type conforming to the protocol.</font></div><div class=""><font color="#5856d6" face="Menlo" class="">&nbsp; &nbsp; // This would require Swift to recognize that members typed with the protocol itself</font></div><div class=""><font color="#5856d6" face="Menlo" class="">&nbsp; &nbsp; // also conform to the protocol.<br class=""></font><span style="font-family: Menlo;" class="">&nbsp; &nbsp; @forward(_Cluster) private&nbsp;var&nbsp;_instance:&nbsp;_Cluster</span></div><div class=""><span style="font-family: Menlo;" class=""><br class=""></span></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; // FooBar is a type that conforms to both Foo and Bar protocols</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; @forward(Foo, Bar) private let fooBar: FooBar</font><br class=""></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; ...<br class=""></font><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><div class=""><font face="Menlo" class="">}</font></div></div></div></div><div class=""><br class=""></div><div class="">Matthew</div><br class=""><div><blockquote type="cite" class=""><div class="">On Dec 7, 2015, at 3:33 PM, David Owens II 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=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Often it is the case where one might want to implement a type that provides an interface but has inner components that actually handle the implementation. In those cases, we end up with a lot of boiler-plate code that simply turns around and invokes the on the instance.</div><div class=""><br class=""></div><div class="">Let’s take the example of class clusters:</div><div class=""><br class=""></div><div class=""><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><span style="font-family: Menlo;" class="">private protocol&nbsp;_Cluster {</span></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;func&nbsp;description() -&gt;&nbsp;String<br class="">}</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">class&nbsp;Cluster: _Cluster {</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;private&nbsp;var&nbsp;_instance:&nbsp;_Cluster</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;init(name:&nbsp;String) {</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;_instance&nbsp;=&nbsp;_ClusterString(name: name)</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;}</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;init(value:&nbsp;Int) {</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;_instance&nbsp;=&nbsp;_ClusterValue(value: value)</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;}</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; // this is pure boiler-plate</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;func&nbsp;description() -&gt;&nbsp;String&nbsp;{</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;_instance.description()</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;}</font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">private&nbsp;class&nbsp;_ClusterString:&nbsp;_Cluster&nbsp;{</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;private&nbsp;var&nbsp;name:&nbsp;String</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;init(name:&nbsp;String) {&nbsp;self.name&nbsp;= name }</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;func&nbsp;description() -&gt;&nbsp;String&nbsp;{</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;"_ClusterString:&nbsp;\(name)"</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;}</font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">private&nbsp;class&nbsp;_ClusterValue:&nbsp;_Cluster&nbsp;{</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;private&nbsp;var&nbsp;value:&nbsp;Int</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;init(value:&nbsp;Int) {&nbsp;self.value&nbsp;= value }</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;func&nbsp;description() -&gt;&nbsp;String&nbsp;{</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;"_ClusterValue:&nbsp;\(value)"</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;}</font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">let&nbsp;s =&nbsp;Cluster(name:&nbsp;"a string")</font></div><div class=""><font face="Menlo" class="">s.description()</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">let&nbsp;v =&nbsp;Cluster(value:&nbsp;12)</font></div><div class=""><font face="Menlo" class="">v.description()</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div></blockquote></div><div class=""><br class=""></div><div class="">Now, it would be nice to not have to have to implement the boiler-plate (this example only has a single method, so the savings seem minimal).</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><span style="font-family: Menlo;" class="">class&nbsp;Cluster: _Cluster {</span></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;</font><span style="font-family: Menlo;" class="">@forward(_Cluster, _instance)</span></div></div><div class=""><span style="font-family: Menlo;" class=""><br class=""></span></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;private&nbsp;var&nbsp;_instance:&nbsp;_Cluster</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;init(name:&nbsp;String) {</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;_instance&nbsp;=&nbsp;_ClusterString(name: name)</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;}</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;init(value:&nbsp;Int) {</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;_instance&nbsp;=&nbsp;_ClusterValue(value: value)</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;}</font></div></div><div class=""><div class=""><font face="Menlo" class="">}</font></div></div><div class=""><div class=""><br class=""></div></div></blockquote><div class="">The @forward(protocol, instance) attribute lets the compiler know that the _Cluster protocol should be forwarded to the _instance value. The compiler would then generate all of the implementation stubs. Refactoring is also made simple as API changes to _Cluster do not need to be manually reflected on the type.</div><div class=""><br class=""></div><div class="">Another way to solve this problem is with a sufficiently advanced macro system. But that is out-of-scope for v3. However, this seems like it could be a straight-forward enough implementation to support in the mean-time, with an easy path for removal/update if it were to be replaced by a macro system.</div><div class=""><br class=""></div><div class="">-David</div><div class=""><br class=""></div>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=eLFMrKDT8iBxZ-2Fbnk-2BZqvSchNN-2FvYXdceA0T7VxwkAdHmoHOBER0flSpf-2Bzl7KFyJQOxpq5UtXWGtIJ2DIz92t-2FrShEv5HnDrUrVPT1BxznKECbFuAOQL4QSdBYgbvbX4lrsO8J3lRCYYp2Tk9nPsV5MDq2SHpZe2sMzKfGA-2BjgQpro8CqXb2I6Z0FFeply8uhziaJuOETuYdnjYhv4iuK3Bn1hc0vesHfl3NjA5HDc-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=""></body></html>