<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><br><br><div id="AppleMailSignature">Sent from my iPhone</div><div><br>On 23 Jun 2017, at 21:08, Haravikk via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; wrote:<br><br></div><blockquote type="cite"><div><meta http-equiv="Content-Type" content="text/html charset=us-ascii"><br class=""><div><blockquote type="cite" class=""><div class="">On 23 Jun 2017, at 16:20, Mike Kluev &lt;<a href="mailto:mike.kluev@gmail.com" class="">mike.kluev@gmail.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class="">on Fri Jun 23 05:26:11 CDT 2017&nbsp;Haravikk swift-evolution at <a href="http://haravikk.me/" class="">haravikk.me</a> wrote:</div><div class=""><br class=""></div><div class="">&gt; Not sure what you mean by added indirection here, the following seems perfectly straightforward to me:<br class=""></div><div class="">&gt;&nbsp;</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">&gt;&nbsp;        </span>protocol Foo {</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">&gt;&nbsp;                </span>var someValue:Int { get set }</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">&gt;&nbsp;                </span>func a() -&gt; Any?</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">&gt;&nbsp;        </span>}</div><div class="">&gt;&nbsp;<br class=""></div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">&gt;&nbsp;        </span>extension Foo {</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">&gt;&nbsp;                </span>func a() -&gt; Any? { return self.someValue }</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">&gt;&nbsp;        </span>}</div><div class="">&gt;&nbsp;<br class=""></div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">&gt;&nbsp;        </span>struct ValueSemantics:Foo { var someValue:Int }</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">&gt;&nbsp;        </span>class ReferenceSemantics:Foo {</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">&gt;&nbsp;                </span>var someValue:Int { return nil }</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">&gt;&nbsp;        </span>}</div><div class="">&gt;&nbsp;<br class=""></div><div class="">&gt; There is no added access overhead here, the only difference is that the protocol itself leaves it up to&nbsp;</div><div class="">&gt; implementations whether someValue is stored or computed.</div><div class=""><br class=""></div><div class="">in real cases there would be more variables:</div><div class=""><br class=""></div><div class=""><div class="">//============</div></div><div class="">protocol P1 { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // #noise<br class=""></div><div class=""><div class="">&nbsp; &nbsp; var var1: Int { get set } &nbsp; &nbsp; &nbsp; // #noise</div><div class="">&nbsp; &nbsp; var var2: Int { get set } &nbsp; &nbsp; &nbsp; // #noise</div><div class="">&nbsp; &nbsp; // ... &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// #noise x 100</div><div class="">&nbsp; &nbsp; var var100: Int { get set } &nbsp; &nbsp; // #noise</div><div class="">&nbsp; &nbsp;&nbsp;</div><div class="">&nbsp; &nbsp; func foo1() -&gt; Int &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// #noise</div><div class="">&nbsp; &nbsp; func foo2() -&gt; Int &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// #noise</div><div class="">&nbsp; &nbsp; // ... &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// #noise x 100</div><div class="">&nbsp; &nbsp; func foo100() -&gt; Int &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// #noise</div><div class="">}</div><div class=""><br class=""></div><div class="">extension P1 { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// #noise</div><div class="">&nbsp; &nbsp; func foo1() -&gt; Int { return var1 * 2 }</div><div class="">&nbsp; &nbsp; func foo2() -&gt; Int { return var2 * 2 }</div><div class="">&nbsp; &nbsp; // ...</div><div class="">&nbsp; &nbsp; func foo100() -&gt; Int { return var100 * 2 }</div><div class="">}</div><div class=""><br class=""></div><div class="">struct S1: P1 {</div><div class="">&nbsp; &nbsp; var var1: Int &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // #noise</div><div class="">&nbsp; &nbsp; var var2: Int &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // #noise</div><div class="">&nbsp; &nbsp; // ... &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// #noise x 100</div><div class="">&nbsp; &nbsp; var var100: Int &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // #noise</div><div class="">}</div><div class=""><br class=""></div><div class="">class C1: P1 {</div><div class="">&nbsp; &nbsp; var var1: Int = 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // #noise</div><div class="">&nbsp; &nbsp; var var2: Int = 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // #noise</div><div class="">&nbsp; &nbsp; // ... &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// #noise x 100</div><div class="">&nbsp; &nbsp; var var100: Int = 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // #noise</div><div class="">}</div><div class=""><div class="">//============</div></div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">lots of noise and violations of DRY. you may try to mitigate it by putting all those storage into another struct, that was the indirection i was thinking about:</div></div></div></div></blockquote><br class=""></div><div>Maybe, but the whole point of the protocol is that it's a contract</div></div></blockquote><div><br></div><div>... and this is why I do not like code in then (see default method in protocol extensions essentially just to allow code sharing across structs) :P.</div><div><br></div><br><blockquote type="cite"><div><div>, it's up to the implementing types how the properties are actually stored (if at all); in that respect it's not noise, as it's necessary.</div><div><br class=""></div><div>The shorthand you're proposing is effectively masquerading delegation as extension; I'm not sure making it look like extension is the right way togo, but delegation is absolutely something I support, just not in this style.</div><div><br class=""></div><div>Currently there is a lot of boilerplate around things like type-erased wrappers, where you might get a class that looks like:</div><div><br class=""></div><div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>class MyWrapper&lt;S:Foo&gt;:Foo {</font></div><div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>struct foo:S</font></div><div><font face="Monaco" class=""><br class=""></font></div><div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>func someMethodOfFoo() { foo.someMethodOfFoo() }</font></div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>func someOtherMethodOfFoo() { foo.someOtherMethodOfFoo() }</font><div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</font></div><div><br class=""></div><div>It's the same basic problem, except that I don't necessarily want everything to be implemented by my enclosed struct. This is why I'd prefer a solution that's more explicit about the fact that there's delegation going on, and more flexible about how things are delegated. This is what I mean:</div><div><br class=""></div><div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>protocol Foo {</font></div><div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>var someValue:Int { get set }</font></div><div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>func someMethod() -&gt; Int</font></div><div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</font></div><div><font face="Monaco" class=""><br class=""></font></div><div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>struct ValueType:Foo {</font></div><div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>var someValue:Int</font></div><div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>func someMethod() { return self.someValue }</font></div><div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</font></div><div><font face="Monaco" class=""><br class=""></font></div><div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>class ReferenceType:Foo {</font></div><div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>var foo:ValueType implements Foo // This is the important bit</font></div><div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</font></div><div><br class=""></div><div>It's got one extra step, but is explicit that there's delegation involved, and without suggesting some kind of hierarchy that doesn't exist. In this case ValueType needn't even conform to Foo at all, just as long it has properties and methods that are a match; in this way we could potentially conform to Foo using multiple delegates that each implement a little bit of the protocol.</div><div><br class=""></div><div>Another possible syntax is:</div><div><br class=""></div><div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>class ReferenceType:Foo {</font></div><div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>delegate(Foo) var foo:ValueType</font></div><div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}</font></div><div><br class=""></div><div>This may be slightly better as it explicitly references to delegation, but it's the same idea; in the brackets you put one or more types, or members of types, that the property is a delegate for.</div></div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>swift-evolution mailing list</span><br><span><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></div></blockquote></body></html>