<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Jul 19, 2016 at 6:26 PM, Peter Livesey via swift-evolution <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div>I&#39;m new to this thread, but I&#39;ve read every email so far. There are a few things I find confusing with the proposal, so I&#39;ll try to sum up what I see so far:</div><div><br></div><div>1. I don&#39;t understand what problem this solves?</div><div><br></div><div>It seems like for 3rd party libraries only, we are afraid that people will subclass things when they shouldn&#39;t? Is this a real problem? </div></div></blockquote><div>Yes. It is a real problem. If you vend a library for long enough and make some change to a class that you never intended to be subclassed,  you are likely to find out that you have broken client code. </div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div><br></div><div>What are people frustrated by? Are 3rd party developers frustrated that they can&#39;t specify this? But they can already - with final?</div></div></blockquote><div><br></div><div>`final` is not the same as sealed. `final` classes are sealed but sealed classes are not necessarily final.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div> Are consumers frustrated that they&#39;re allowed to subclass when they shouldn&#39;t? I can&#39;t imagine anyone wanting either of these things.</div></div></blockquote><div><br></div><div>I have been frustrated by having trouble correctly subclassing something only to find out that I shouldn&#39;t have tried. Yes, read the documentation, but documentation can often be subtle with &#39;don&#39;t  subclass this&#39;</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div><br></div><div>2. It seems that a consistent argument is that this &#39;forces developers to think about it&#39;.</div><div><br></div><div>I don&#39;t understand this at all. It&#39;s not a required keyword, so why does it force me to do anything? I leave it out - there&#39;s no error, no reminder, no forcing.</div></div></blockquote><div><br></div><div>What happens when you ship the library and no-one can subclass anything, even the types you intended for them to subclass? Do you not have or ship any tests or demo code which uses the library as a dependency?</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div>3. It&#39;s a crazy specific and complex rule:</div><div><br></div><div>&quot;You can&#39;t subclass it only if it&#39;s public and only if it&#39;s in a different module. Unless it&#39;s testable, then it&#39;s ok.&quot; Not only does this make many assumptions about the roles of modules (not all modules are 3rd party libraries), but it&#39;s a crazy rule for people to memorize. It definitely violates the rule of least surprise in my opinion and I bet most people running into this error will think: &quot;What is this?&quot;.</div></div></blockquote><div><br></div><div>I memorized it from the first. Foreign public code must explicitly trust me for this to happen. </div><div><br></div><div>`@testable` is it&#39;s own skeleton key. This is not new. Why can I see `internal members? `@testable`.</div><div><br></div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div><br></div><div>4. Please can we keep swift simple</div><div><br></div><div>Swift has ~94 keywords so far (I know, that&#39;s not the best way to measure complexity of a language), but does this problem really warrant it&#39;s own keyword? Swift is beautiful because of how it balances power and complexity. These types of rules add so much complexity for very little benefit.</div></div></blockquote><div><br></div><div>The core of swift is simple. You can teach basics up to intermediate concepts pretty quickly. Advanced swift is already complex for great reason. The added complexity especially beneficial because it will force a conversation about this decision. </div><div>relatively new swift developer: &quot;Why can&#39;t I subclass anything from this module that I wrote?&quot; </div><div>me: &quot;because you haven&#39;t explicitly stated what should be subclassed and what shouldn&#39;t&quot;</div><div>This speaks directly to point #2.</div><div><br></div><div><br></div><div><br></div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div><br></div><div>5. If you think subclassing is dangerous by default, turn it off by default.</div><div><br></div><div>Why are we special casing 3rd party libraries? </div></div></blockquote><div>Because it is  foreign code. Code that you don&#39;t control. You say &#39;not every module is 3rd party.&#39; true. You control that and can easily open classes in the module because you control it. In opening it yourself, you are deciding and explicitly stating that it should be open. This again speaks to point #2.</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div>Since when does a language assume how it&#39;s being consumed?</div></div></blockquote><div>Choosing to make something a module is an attempt to separate off some bit of logic. The walls are a decision. If you control it all and you are bothered by the wall, put it in the same module. </div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div> Again, this goes back to the assumption that all modules are 3rd party libraries with well thought out APIs. I don&#39;t think this is true at all…</div></div></blockquote><div>&quot;Abandon all hope, ye who enter?&quot; How is it wrong to try to make this a reality? </div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div>If we truly believe that subclassing is dangerous unless the class is designed for it, then lets do it everywhere, not just for public classes. I don&#39;t think I&#39;d vote for this, but I will admit it at least has consistency and simplicity.</div></div></blockquote><div><br></div><div>So… the only way that you would consider this change is if we changed it to be obviously less useful and, because it wouldn&#39;t be useful with that change, it is not a good change?</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div><br></div><div>Summary</div><div><br></div><div>I think it&#39;s dangerous for a language to assume how code is written and used. </div></div></blockquote><div><br></div><div>I think that it is the job of the language&#39;s maintainers to guide use of the language. </div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div>This proposal assumes that classes are written in a certain way, and code is consumed in a certain way.</div></div></blockquote><div><br></div><div>This proposal steers the writers and consumers of code written toward an envisioned &#39;golden path&#39;.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div> I think Swift should stay flexible while allowing for people to be expressive (e.g. the final keyword is AWESOME).</div></div></blockquote><div>sealed-by-default does not reduce that flexibility. It increases it. </div><div>&quot;oops, I have to open a class that I already shipped &quot; &lt;- entirely possible to do without breaking compatibility after adoption of this proposal</div><div>&quot;oops. I have to seal a class that I already shipped&quot; &lt;- not possible to do without breaking compatibility. </div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div> The pros here seem to suggest that we&#39;ll fix a bunch of bugs where subclassing was done by mistake. The cons seem to be that it shackles developers when people forget to add this keyword (which will happen a lot...because there are 94 others to remember how to use correctly).</div></div></blockquote><div><br></div><div>Do we really believe that we cannot and will not teach our developers to do something? &quot;abandon all hope&quot; indeed. Developers who ship APIs without audits, without demo code or tests which call this out, and–finally–without listening to clients who complain about this are not really a great metric, are they?</div><div><br></div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div><br></div></div><br><div class="gmail_quote"><div><div class="h5"><div dir="ltr">On Tue, Jul 19, 2016 at 2:17 PM Goffredo Marocchi via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:<br></div></div></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div><div class="h5"><div dir="auto"><div><div style="direction:inherit"><br></div><br>Sent from my iPhone</div></div><div dir="auto"><div><br>On 19 Jul 2016, at 21:41, David Owens II &lt;<a href="mailto:david@owensd.io" target="_blank">david@owensd.io</a>&gt; wrote:<br><br></div><blockquote type="cite"><div><br><div><blockquote type="cite"><div>On Jul 19, 2016, at 11:37 AM, L. Mihalkovic via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br><div><div dir="auto"><div><br><br><div>Regards</div>(From<span> mobile)</span></div><div><br>On Jul 19, 2016, at 8:19 PM, Goffredo Marocchi via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:<br><br></div><blockquote type="cite"><div><div><div style="direction:inherit"><br></div>Sent from my iPhone</div><div style="direction:inherit"><br></div><blockquote type="cite"><div><span></span><span>&lt;off-topic&gt;</span><br><span>Cocoa currently hides the boilerplate for all of these wonderful constructs behind amazingly effective runtime acrobatics. This fits perfectly into Objective-C, and it also works very well in Swift. But such features could be in better harmony with Swift&#39;s unique set of language constructs if their boilerplate was hidden behind amazingly effective **compile-time** acrobatics instead.</span><br><span></span><br><span>Such compile-time acrobatics are hard to perform today, and it is possible that the ability to create such systems will forever remain an advanced skill, just like forging runtime magic requires advanced skills in Objective-C.</span><br></div></blockquote><div style="direction:inherit"><br></div><div style="direction:inherit">... rantish...</div><div style="direction:inherit"><br></div><div style="direction:inherit">I am still not convinced that even the best compiler can fully replace what a powerful runtime can provide no matter the acrobatics you put in in terms of compiler introduced utility code/constructs or the code analysis efforts you can put in at compile time</div></div></blockquote><div><br></div><div>That is a fact back by some interesting papers. By it is also true that one cannot always be used in place of the other.</div></div></div></blockquote></div><br><div>While it is true that the compiler cannot fully replace everything, it can help with many types of errors that are hard to catch at runtime.</div><div><br></div><div>I’ll reiterate this again: this proposal does *not* prevent Swift from building language mechanism to allow for this type of behavior though. The fact is, Swift APIs are heavily value or value semantics so the lack of inheritance on classes is not going to be the primary reason you cannot monkey patch something.</div><div><br></div><div>What this proposal does say is this: there is no “safe” way to achieve this type of behavior that the API authors either intentionally left out or left out because of an omission. </div><div><br></div><div>If you are subclassing a class in Swift, under this proposal, you can be sure of one thing: the author explicitly made it so you’d be able to. We can argue if they did so with diligence, but that’s mostly immaterial to the discussion.</div><div><br></div><div>The fact is, in order to allow monkey patching, Swift is going to need to answer many questions that it still has yet to answer, such as how reflection is really going to work. However, with these more restrictive defaults, it’s possible to extend the language to provide runtime monkey patching that can be more easily audited both in source code and at runtime. Instead of API authors just seeing crashes in their libraries and not realizing that someone swizzled a method, we would now be able to mark who did the swizzling and which functions were actually swizzled.</div><div><br></div><div>An example of how this *could* look would be something like this:</div><div><br></div><div><font face="Menlo">struct Person { /* This is defined in module A */</font></div><div><font face="Menlo">    // a bunch of fields</font></div><div><font face="Menlo">    var birthDate: Date { get set }</font></div><div><font face="Menlo"><br></font></div><div><font face="Menlo">    func calculateAge() -&gt; Int { return 12; }</font></div><div><font face="Menlo">}</font></div><div><font face="Menlo"><br></font></div><div>Obviously there is a bug in `calculateAge`. How could we fix it? Well, in your app framework (or some other target as needed) as we don’t have the ability to fix module A directly:</div><div><font face="Menlo"><br></font></div><div><font face="Menlo">extension Person {</font></div><div><font face="Menlo">    @replaceMethodImplementation func calculateAge() -&gt; Int { /* better implementation */ }</font></div><div><font face="Menlo">}</font></div><div><br></div><div>This would require support within the Swift language and tooling. For one, we’d need the non-optimized code to be distributed so that code within module A used this new implementation of `calculateAge`. However, this is the direction I’d much rather see Swift go. The ability to annotate code properly as monkey patches so we can audit them, track them, version them, and identify them clearly both at compile time and runtime.</div><div><br></div><div>I’m all for Swift getting the right underlying model. After that, we can address a better way to provide the necessary means to monkey patch and change behavior, but first the fundamentals need to be nailed properly.</div></div></blockquote><div style="direction:inherit"><br></div></div><div dir="auto"><div style="direction:inherit">Agreed, but we need to get ourselves some metrics and not to be afraid to considered annoying non true believers :). As more coders use Swift in their apps for some portions or the entirety of their codebase, are we seeing less bugs? When will it be proper to collect the data in a productive non biased way? I think it&#39;ll be very interesting as more stats are available other than LOC ones.</div><div style="direction:inherit"><br></div><div style="direction:inherit">We desire to have Swift run in all possible scenarios, complex video games included, and being a heavily value type based language with many built-in components using CoW semantics (sizeable in memory copies when some coders may forget it will happen). There is a reason why academia and a lot of coders back then we&#39;re pushing people towards reference types and pass by reference semantics and away from how C dealt with big structs and function pointers to achieve similar features.</div><div style="direction:inherit"><br></div><blockquote type="cite"><div><div><br></div><div>-David</div></div></blockquote></div></div></div>_______________________________________________<span class=""><br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
</span></blockquote></div>
<br>_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
<br></blockquote></div><br></div></div>