<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 Sep 13, 2016, at 10:29 AM, Benjamin Spratling 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="">Well, then also add an unowned convenience.<div class="">But I’ve never been handed a story from UX that said, “As a user, when ____ I want the app to crash.”</div><div class="">Using weak, the compiler can tell me when I’ve missed a possible case where it’s nil.</div></div></div></blockquote><div><br class=""></div>Honestly, I’d be fine with / prefer only allowing unowned (at all) if it’s @noescape, if that, requiring strong or weak for anything that escapes. That seems to go along with swift’s emphasis on safety.&nbsp;</div><div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">But the point here is to get closure references that don’t create retain cycles. &nbsp;Obviously, there’s desire for both weak and unowned variants without the syntactic overhead of a full closure.<br class=""><div class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Sep 13, 2016, at 12:22 PM, Karl Wagner &lt;<a href="mailto:razielim@gmail.com" class="">razielim@gmail.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class=""><div id="edo-message" class=""><div class="">Weak references can have a non-trivial amount of overhead in high-performance code. In some cases you can guarantee that a pointer should never be null - and that if it is, a serious logic error has occcurred and you *should* crash.</div><div class=""><br class=""></div><div class="">I prefer crashing to running in an inconsistent state. Who knows what can happen in the latter case - data corruption? I'd prefer to crash, get a report and fix the bug.</div><div class=""><br class=""></div><div class="">Karl<br class=""><br class=""><div style="font-family: 'Helvetica Neue','Helvetica',Helvetica,Arial,sans-serif;font:'-apple-system-body';" class=""><a href="https://itunes.apple.com/app/apple-store/id922793622?pt=814382&amp;mt=8&amp;ct=how_i_email" class="">This</a> is how I Email now</div></div></div><div id="edo-original" class=""><div class=""><br class=""><br class=""><blockquote type="cite" style="margin:1ex 0 0 0;border-left:1px #ccc solid;padding-left:0.5ex;" class=""><div class="">On Sep 13, 2016 at 11:07 am, &lt;<a href="mailto:swift-evolution@swift.org" class="">Benjamin Spratling via swift-evolution</a>&gt; wrote:<br class=""><br class=""></div><div class=""><pre class="">Nick, I like where you’re headed with the instance-methods-as-closures idea.  Here’s where I’m headed with it:<br class=""><br class="">Closures are too often used to write the contents of what should be another function, producing code similar to the “pyramid of doom” avoided by guard.  I now generally write as little code as possible in a closure, and use it merely to dispatch out to a private function as quickly as possible.  This means I really do want classes to reference their own functions.  I look at closures more as providing the captured scope as the "void* context" that goes along with an old C function reference, as opposed to being the scope in which the code should be written.<br class=""><br class="">I loved the “get a closure to implicit self using nothing but the function name” feature of Swift, but after running over a dead line by spending 1.5 days with 3 other developers trying to find a retain cycle caused by its use, we added it to our list of reasons to not merge code, hereafter referred to as “the list".  This from a guy who used to write flawless manual retain/release code, back in the day.<br class=""><br class="">Incidentally, we also put “unowned" on "the list".  We always use “weak” instead.  The bottom line is unowned CAN crash, and weak can’t.  There is no way to know if a call to unowned will crash or not.  So we prefer to write code that can’t crash. (No, we don’t force-unwrap weak optionals, “!” is on "the list”, and we nicknamed it the “Russian Roulette operator”)  So instead of “something like [unowned self] syntax...”, I’m suggesting “something like [weak self] syntax..."<br class=""><br class="">So I’d prefer something like “weakself?.functionName” to produce a closure which wraps a weak-self reference and a call to the given method if self isn’t nil.  This seems like a trivial task for the compiler when return types are Void or Optional.  Given the expectations of optional chaining, and the zeroing behavior of any not-owned relationship, I’m not sure it makes sense to demand a non-optional return type for a call to a parent.  So I don’t think such a feature even needs to worry about what if the expected return type isn’t optional.<br class=""><br class="">I’d be happy to see any of the following syntaxes:<br class=""><br class="">weakself.functionName<br class="">weakself?.functionName<br class="">?functionName<br class="">welf.functionName<br class="">self?.functionName<br class="">weak(self)?.functionName<br class=""><br class="">Obviously, one work around is to declare a protocol, and pass self, letting the receiving class store a weak reference.  But declaring protocols for every single closure reference is a bit tedious.  Literally just the back and forth on naming them is a waste of time.  And there’s the running joke that we’d just tack “able” on the end of the method name.<br class=""><br class="">Another work around is to create several generic classes which generate closures which weakly capture self and an unapplied method reference, and overloaded functions or operators to provide the correct class.  Unfortunately, this still requires writing “self” explicitly, and also explicitly writing the type of self to obtain an unapplied method reference.<br class=""><br class="">Given our experience, I would consider giving a warning when an implicit-self closure goes into an @escaping context.<br class=""><br class="">        class SomeClass {<br class="">        var someFunction:(()-&gt;())?<br class="">        func setup() {<br class="">                prepare(closure: trigger)        //this should probably be a warning<br class="">        }<br class="">        func prepare(closure:@escaping()-&gt;()) {<br class="">                someFunction = closure<br class="">        }<br class="">        func trigger() {<br class="">        }<br class="">        }<br class=""><br class="">Self is already required when used inside an closure, for exactly this reason.<br class="">Perhaps we should require the developer to write explicit “self” or “self?” to indicate strong or weak capture of self.<br class="">        prepare(closure: self.trigger)        //ok, strong self<br class="">        prepare(closure: self?.trigger)        //ok, weak self<br class="">Or if they would like to use unowned, <br class="">        prepare(closure: RussianRoulette(self).trigger)        // ;-)<br class=""><br class="">In the end, however, closures do occasionally capture non-instance-property scope, which would need to be adapted in the wrapping closure around the call to another method, so the number of no-adapting-needed methods may be quite low.  I expect given current priorities that this wouldn’t make it in to Swift 3.1.  But given the severity of the consequences and the simplicity of the implementation, I would hope it would make it by Swift 4.<br class=""><br class="">-Ben Spratling<br class=""><br class="">_______________________________________________<br class="">swift-evolution mailing <a dir="ltr" href="mailto:listswift-evolution@swift.orghttps" x-apple-data-detectors="true" x-apple-data-detectors-type="link" x-apple-data-detectors-result="3" class="">list</a><br class=""><a dir="ltr" href="mailto:listswift-evolution@swift.orghttps" x-apple-data-detectors="true" x-apple-data-detectors-type="link" x-apple-data-detectors-result="3" class="">swift-evolution@swift.org</a><br class=""><a dir="ltr" href="mailto:listswift-evolution@swift.orghttps" x-apple-data-detectors="true" x-apple-data-detectors-type="link" x-apple-data-detectors-result="3" class="">https</a>://<a href="http://lists.swift.org/mailman/listinfo/swift-evolution" class="">lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></pre></div></blockquote></div></div></div></div></blockquote></div><br class=""></div></div></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>