<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=""><br class=""><div><blockquote type="cite" class=""><div class="">On Aug 22, 2016, at 11:32 PM, Xiaodi Wu <<a href="mailto:xiaodi.wu@gmail.com" class="">xiaodi.wu@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">On Mon, Aug 22, 2016 at 11:59 PM, Jonathan Hull via swift-evolution <span dir="ltr" class=""><<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>></span> wrote:<br class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi everyone,<br class="">
<br class="">
We talked about this before when we were discussing mixins, and there seemed to be generally positive feelings towards it as a feature for the future.</blockquote><div class=""><br class=""></div><div class="">It's been some time now since the original discussion, so perhaps you could refresh our collective memory (or at least, mine): although it *seems* like this feature might be useful, I can't recall a concrete use case where I've felt like I needed this feature--do you have some examples?</div></div></div></div></div></blockquote><div><br class=""></div><div>Ideally, the biggest use is that it helps to (partially) solve the diamond problem (and similar issues) by forcing/allowing disambiguation when there are multiple protocols being conformed to. This will become more of an issue if we allow protocols or extensions to add storage. Your proposed syntax actually does a better job of it than mine because mine was always shown as attached to some sort of implementation, whereas yours could potentially allow access to a default implementation under a new name.</div><div><br class=""></div><div>Other than that, it generally allows us to bypass/mitigate conflicts between protocols. In the current version, you are unable to conform to both protocols (either because it won’t compile or because you can’t satisfy the semantics of both protocols) without designing the protocols together to avoid conflicts. (I have definitely had to go back and rename/refactor properties on a protocol for this reason… which I couldn’t have done if I didn’t control both protocols).</div><div><br class=""></div><div>Take a look at Eiffel’s ‘rename’ & ’select’ features for similar functionality and use-cases.</div><div><br class=""></div><div>Ultimately, this is a step in the direction of having true mixins.</div><div><br class=""></div><div><br class=""></div><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""> I am fairly certain this affects the ABI though, so I thought I would bring it up now.</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br class="">
If two protocols have methods/properties with the same name, but different signatures, we need a way to distinguish between them when attempting to conform to both.<br class="">
<br class="">
protocol A {<br class="">
var x:Int {get set}<br class="">
}<br class="">
<br class="">
protocol B {<br class="">
var x:Double {get set}<br class="">
}<br class=""></blockquote><div class=""><br class=""></div><div class="">Methods can be overloaded that differ in arguments or return type, so it seems like this problem mainly exists with *properties* that differ in type--am I wrong?</div></div></div></div></div></blockquote><div><br class=""></div><div>There is also the case of functions with the same name and signature, but different semantics. There may be no single implementation which simultaneously satisfies the semantics for both protocols. By renaming one of the functions, we are able to provide separate implementations for each requirement (which allows both protocols to function as intended).</div><div><br class=""></div><div>There may also be functions in different protocols with different names but the same semantics and signature. This will allow a single implementation to satisfy both protocols without duplication.</div><div><br class=""></div><div>Finally, we may want to rename an inherited default implementation to avoid conflicting with another protocol's default implementation in cases where we don’t want to override it.</div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""> One possibility is to allow a struct/class/enum to conform to the protocol while renaming one (or both) of the clashing methods:</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br class="">
struct C: A,B {<br class="">
var x:Int<br class="">
var y:Double implements B.x<br class="">
}<br class="">
<br class="">
The conforming method/property would still have to have the same signature, but could have a different name (and parameter labels). It would also allow protocol methods which have identical signatures and semantics, but different names to be implemented using the same method (i.e ‘implements D.z & E.w’).<br class="">
<br class="">
When something is cast to the protocol (say ‘as B’), then calling the property (e.g. ‘x’) would end up calling the implementation of the renamed property ( ‘y’ in this example) on the conforming type.<br class=""></blockquote><div class=""><br class=""></div><div class="">Reflecting on this proposed change, it occurs to me that something of value would be lost, and I think that this something is actually rather valuable:</div><div class=""><br class=""></div><div class="">Today, when I see that a type conforms to (for example) Sequence, I know that certain methods and/or properties exist on that type. Protocol conformance guarantees a certain API, not just certain semantics.</div></div></div></div></div></blockquote><div><br class=""></div><div>It isn’t actually lost, however. When working with it as a Sequence (for example), that API would be intact using the original names. It is only when working with it as its own type that the renaming would have an effect.</div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class="">Perhaps one way to mitigate this loss would be to have any renamed members listed *in the declaration of conformance*, something like this (with some additional bikeshedding):</div><div class=""><br class=""></div><div class="">```</div><div class="">struct MyGreatType : Sequence (count => length) {</div><div class=""> // MyGreatType conforms to Sequence but renames `count` to `length`</div><div class="">}</div><div class="">```</div></div></div></div></blockquote><div><br class=""></div><div>Yes, putting it in the conformance declaration is a definite possibility we should consider.</div><div><br class=""></div><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""><br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I think we would also want a way to retroactively conform using existing properties/methods in an extension declaring conformance. Not sure what the best syntax for that would be. Off the top of my head (though I would love to have something with less cruft):<br class="">
<br class="">
extension D:B {<br class="">
@conform(to: B.x, with: D.y)<br class="">
}<br class="">
<br class="">
or maybe just:<br class="">
<br class="">
extension D:B {<br class="">
D.y implements B.x<br class="">
}<br class=""></blockquote><div class=""><br class=""></div><div class="">If renamed members are declared along with protocol conformance, then the syntax for retroactive modeling follows naturally:</div><div class=""><br class=""></div><div class="">```</div><div class="">extension D : B (x => y) { }</div><div class="">// again, the actual notation here is ugly</div><div class="">// but the underlying idea, I think, is worth considering</div><div class="">```</div></div></div></div></div></blockquote><div><br class=""></div><div>Yup</div><div><br class=""></div><div>One thing I like about this is that it helps to solve the diamond problem. ‘x’ could be a default implementation in B which D does not override. I think this is an important case which my original proposal didn’t address fully.</div><div><br class=""></div><div>We should keep bikeshedding the syntax though...</div></div><br class=""><div class="">Thanks,</div><div class="">Jon</div><div class=""><br class=""></div><div class=""><br class=""></div></body></html>