<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=""><blockquote type="cite" class="">On Aug 26, 2016, at 3:58 PM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" class="">xiaodi.wu@gmail.com</a>&gt; wrote:<br class=""></blockquote><div><blockquote type="cite" class=""><br class="Apple-interchange-newline"><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">On Fri, Aug 26, 2016 at 3:43 PM, Charles Srstka<span class="Apple-converted-space">&nbsp;</span></span><span dir="ltr" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">&lt;<a href="mailto:cocoadev@charlessoft.com" target="_blank" class="">cocoadev@charlessoft.com</a>&gt;</span><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class=""><span class="Apple-converted-space">&nbsp;</span></span><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">wrote:</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote class="gmail_quote" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;"><div style="word-wrap: break-word;" class=""><div class=""><br class=""></div><div class=""><span class=""><div class="">On Aug 26, 2016, at 3:19 PM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank" class="">xiaodi.wu@gmail.com</a>&gt; wrote:</div><br class=""></span><div class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><span class=""><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;"><div style="word-wrap: break-word;" class=""><span class=""><div class=""><blockquote type="cite" class=""><div class=""><div class=""></div></div></blockquote></div></span></div></blockquote><blockquote type="cite" class=""><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;"><div style="word-wrap: break-word;" class=""><span class=""><div class=""><blockquote type="cite" class=""><div class=""><div class="">Why? S.foo() is visible throughout the module, but outside this file, S.foo() doesn't override anything. Why should it be marked as an `override` when, as you say, the generated interface shows no sign of conformance to P?</div><div class="">In addition, how would you justify a requirement to fiddle with these keywords when someone simply refactors an internally visible type with no private members from one file to another? Your proposed rule just broke copy-and-paste...</div></div></blockquote></div><div class=""><br class=""></div></span><div class="">Because it indicates the programmer’s *intent.* If the protocol is visible at the time you’re writing the declaration for S.foo(), then you should have to tell the compiler what you mean by that and what you’re doing with it.</div></div></blockquote><div class=""><br class=""></div><div class="">Where a type is located in relation to a protocol is a poor proxy for whether one was written _before_ the other. And while the writer's most likely intent might differ depending on the order in which two things are written, how one declares members on a type should not be determined by a set of arbitrary rules for the compiler to guess whether the type or protocol was written first. This kind of functionality, if you want it, might be appropriate for a linter. It could probably even look at last modified dates, or with a git repo, go line by line to see when each piece of the code was written.</div></blockquote><div class=""><br class=""></div></span><div class="">Why should it matter when the programmer wrote it?</div></div></div></div></div></div></div></div></blockquote><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">I don't know--that's your suggestion, not mine: "If the protocol is visible at the time you’re writing the declaration for S.foo(), then you should have to tell the compiler&nbsp;what you mean by that..."</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">&nbsp;</div><blockquote class="gmail_quote" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;"><div style="word-wrap: break-word;" class=""><div class=""><div class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class="">One is the declaration, the other is an add-on to it. Conceptually, the type is constructed first, and then things are bolted on (and in Objective-C, that’s literally what happened; I don’t know how it is implemented in Swift, but conceptually this is how the mental model works).</div><div class=""><br class=""></div><div class="">Should I not have to add an “override” keyword to a subclass method simply because I wrote that method first and only refactored it into a superclass method after the fact?</div><div class=""><br class=""></div><div class="">This seems like a fairly silly objection, IMO.</div></div></div></div></div></div></div><span class=""><div class=""><blockquote type="cite" class=""><div class=""></div></blockquote></div></span></div></blockquote><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">I agree, it seems silly. Can you explain what you meant?<br class=""></div></div></blockquote><div><br class=""></div><div>Think of it—even if you wrote the whole thing—as if each file were written by a different person. The programmer who wrote File A defines the type. The programmer who wrote File B added conformance to a protocol to the type. Conceptually, one comes before the other, since the type has to be made before it can be extended, yes?</div><div><br class=""></div><div>And I don’t know about you, but when I add methods to a type whose purpose are to satisfy a protocol, I put them near the declaration of conformance, not somewhere on the other side of the universe. If I’m retroactively adding conformance to something in a different translation unit, then the methods involved originally served some other purpose independent of the protocol. Otherwise, it’s just terrible design, IMO.</div><br class=""><blockquote type="cite" class=""><div class=""><blockquote class="gmail_quote" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;"><div style="word-wrap: break-word;" class=""><span class=""><div class=""><blockquote type="cite" class=""><div class="">On Aug 26, 2016, at 3:23 PM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank" class="">xiaodi.wu@gmail.com</a>&gt; wrote:</div><br class=""><div class=""><blockquote class="gmail_quote" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;"><div style="word-wrap: break-word;" class=""><div class="">If you want it all to compile at the same time, well, we’ve still got access to all the Objective-C runtime functions in Swift. One can also write the assembly by hand. Things like “override” aren’t security features; they’re there to help you do the right thing. If you’re deliberately trying to do the wrong thing, I don’t think that can strictly be prevented.</div></div></blockquote><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" class="">The current syntax is not the "wrong thing"--and a future language feature shouldn't leave a loophole where someone can choose either one or another totally different set of rules for conforming a type to a protocol; there should be one syntax for doing that in Swift.</div></div></blockquote></div><br class=""></span><div class="">The current syntax allows many opportunities to do the wrong thing.</div><div class=""><br class=""></div><div class="">This is the wrong thing:</div><div class=""><br class=""></div><div class="">protocol P {</div><div class=""><span style="white-space: pre-wrap;" class="">        </span>func foo(bar: Baz)</div><div class="">}</div><div class=""><br class=""></div><div class="">extension P {</div><div class=""><span style="white-space: pre-wrap;" class="">        </span>func foo(bar: Baz) {}</div><div class="">}</div><div class=""><br class=""></div><div class="">struct S: P {</div><div class=""><span style="white-space: pre-wrap;" class="">        </span>func foo(baz: Baz) {}</div><div class="">}</div><div class=""><br class=""></div><div class="">Refactoring this can result in another wrong thing:</div><div class=""><br class=""></div><div class="">protocol P {</div><div class=""><span style="white-space: pre-wrap;" class="">        </span>func foo(bar: Baz, qux: Quux)</div><div class="">}</div><div class=""><br class=""></div><div class="">extension P {</div><div class=""><span style="white-space: pre-wrap;" class="">        </span>func foo(bar: Baz) {}</div><div class="">}</div><div class=""><br class=""></div><div class="">etc. etc. etc.</div><div class=""><br class=""></div><div class="">Currently it’s hard for a linter to catch things like this, because there’s no way to know that I *didn’t* mean to define a similarly, but not exactly, named function, just as there’s no way to know that I *didn’t* mean to provide a simplified version of the function in the extension. And etc. If I could tell the compiler what I mean by those declarations, suddenly they it becomes possible to check them for accuracy.</div></div></blockquote><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">Or, instead, you could tell a linter these things if you choose; I'm saying your proposal of having distinct before-the-fact and after-the-fact syntax for protocol conformance doesn't make for a good language feature, IMO.</div></div></blockquote></div><div class=""><br class=""></div><div class="">But that was only one of a set of four options which I presented, of which more are assuredly possible. If you want the syntax to be exactly the same, we could even do that, just by declaring the methods in the extension with no bodies:</div><div class=""><br class=""></div><div class="">extension S: P {</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>conform func foo()</div><div class="">}</div><div class=""><br class=""></div><div class="">Honestly, I’m not married to any one syntax for retroactive conformances; the typical kind are the ones I’m more concerned with, because they offer a great potential for mistakes as compared with the traditional inheritance model, and I’m finding that the increased brittleness is the biggest drawback I’m noticing in refactoring an old Objective-C hierarchy to the Swift protocol-oriented model.</div><br class=""><div class="">Charles</div><div class=""><br class=""></div></body></html>