<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 Jun 26, 2016, at 12:10 PM, Christopher Kornher via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> 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=""><div style="margin: 0px; font-size: 10.8px; line-height: normal; -webkit-text-stroke-color: rgb(0, 0, 0); -webkit-text-stroke-width: initial;" class=""><span style="font-kerning: none" class="">I may be too late for Swift 3, but I am planning to propose changes to the default behavior for closures capturing object references. The introduction of Swift Playgrounds has raised the importance of simplifying the coding of leak-free, crash-free closures. New developers should not have to understand closure memory management to start writing useful and correct code.</span></div><div style="margin: 0px; font-size: 10.8px; line-height: normal; -webkit-text-stroke-color: rgb(0, 0, 0); -webkit-text-stroke-width: initial; min-height: 12px;" class=""><span style="font-kerning: none" class=""></span><br class=""></div><div style="margin: 0px; font-size: 10.8px; line-height: normal; -webkit-text-stroke-color: rgb(0, 0, 0); -webkit-text-stroke-width: initial;" class=""><span style="font-kerning: none" class="">The topic of the closure weak/strong dance has been discussed on this list before. This proposal differs from previous proposals in that it will eliminate the dance altogether by default. I am very interested in hearing others’ opinions as to whether the benefits outweigh the costs of various options.</span></div></div></div></blockquote><div><br class=""></div><div>The problem is that strong reference capture is probably the far more common case.</div><div><br class=""></div><div>If you wanted to say that @noescape closures capture references strongly by default, while escaping closures capture them weakly by default that may be closer to reasonable for most situations but now you have magic behavior with an even greater cognitive overhead. (I wonder if it would be more common that @noescape captures strongly, escaping captures self weak by default but other objects strongly… of course that would have even worse cognitive overhead.)</div><div><br class=""></div><div>No matter what, without a garbage collector you are stuck with sub-optimal solutions for fixing reference cycles. I could imagine a language feature that automatically detected trivial cycles (A -> B -> A) but anything more complex just becomes a form of garbage collection anyway.</div><div><br class=""></div><div>I don’t think there is a way to square this circle. Either you have one “automagic” behavior that is wrong for some cases (whether strong or weak is the default), or you require everyone to spam their closures with explicit capture annotations even if there’s a default “capture everything strongly” variant (see C++ lambdas).</div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="margin: 0px; font-size: 10.8px; line-height: normal; -webkit-text-stroke-color: rgb(0, 0, 0); -webkit-text-stroke-width: initial; min-height: 12px;" class=""><span style="font-kerning: none" class=""></span></div><div style="margin: 0px; font-size: 10.8px; line-height: normal; -webkit-text-stroke-color: rgb(0, 0, 0); -webkit-text-stroke-width: initial; min-height: 12px;" class=""><span style="font-kerning: none" class=""></span><br class=""></div><div style="margin: 0px; font-size: 10.8px; line-height: normal; -webkit-text-stroke-color: rgb(0, 0, 0); -webkit-text-stroke-width: initial;" class=""><span style="font-kerning: none" class="">Use of ‘unowned’ </span></div><div style="margin: 0px; font-size: 10.8px; line-height: normal; -webkit-text-stroke-color: rgb(0, 0, 0); -webkit-text-stroke-width: initial;" class=""><span style="font-kerning: none" class="">————————</span></div><div style="margin: 0px; font-size: 10.8px; line-height: normal; -webkit-text-stroke-color: rgb(0, 0, 0); -webkit-text-stroke-width: initial;" class=""><br class=""></div><div style="margin: 0px; font-size: 10.8px; line-height: normal; -webkit-text-stroke-color: rgb(0, 0, 0); -webkit-text-stroke-width: initial;" class=""><span style="font-kerning: none" class="">I now routinely create closures that capture `self` and other object references as ‘weak’ even if I think that I feel that `unowned ` would be safe. This may not be the absolutely most performant solution, but it is straightforward and robust.</span></div></div></blockquote><div><br class=""></div><div>I agree and our team has adopted the rule that use of unowned is not allowed unless the declaration is private and there is profiler proof that it represents a performance problem, and if used warning comments must be placed in the code. Weak is almost never a performance problem and eliminates the risk of a crash, so it is highly preferable to unowned.</div><div><br class=""></div><div>I’d go so far as to say unowned should be removed; let the user use Unmanaged<T> if they need to capture an unowned reference. They’re entering expert territory anyway.</div><div><br class=""></div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="margin: 0px; font-size: 10.8px; line-height: normal; -webkit-text-stroke-color: rgb(0, 0, 0); -webkit-text-stroke-width: initial; min-height: 12px;" class=""><br class=""><span style="font-kerning: none" class=""></span></div><div style="margin: 0px; font-size: 10.8px; line-height: normal; -webkit-text-stroke-color: rgb(0, 0, 0); -webkit-text-stroke-width: initial;" class=""><span style="font-kerning: none" class="">The core proposal:</span></div><div style="margin: 0px; font-size: 10.8px; line-height: normal; -webkit-text-stroke-color: rgb(0, 0, 0); -webkit-text-stroke-width: initial;" class=""><span style="font-kerning: none" class="">——————</span></div><div style="margin: 0px; font-size: 10.8px; line-height: normal; -webkit-text-stroke-color: rgb(0, 0, 0); -webkit-text-stroke-width: initial; min-height: 12px;" class=""><span style="font-kerning: none" class=""></span><br class=""></div><div style="margin: 0px; font-size: 10.8px; line-height: normal; -webkit-text-stroke-color: rgb(0, 0, 0); -webkit-text-stroke-width: initial;" class=""><span style="font-kerning: none" class="">Closures capturing object references should automatically capture all object references as weak.</span></div><div style="margin: 0px; font-size: 10.8px; line-height: normal; -webkit-text-stroke-color: rgb(0, 0, 0); -webkit-text-stroke-width: initial; min-height: 12px;" class=""><br class=""><span style="font-kerning: none" class=""></span></div></div></blockquote><div><br class=""></div><div>This becomes a form of the Objective-C messages-to-nil-do-nothing problem where you don’t crash but your closure doesn’t do any work (or does half the work!) because the reference(s) are/become nil. It doesn’t save you from reasoning about object lifetime because it is just as easy for the closure to capture the last reference to an object or for the lifetime to differ from the closure lifetime. You’re just trading reference cycles for a different problem.</div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="margin: 0px; font-size: 10.8px; line-height: normal; -webkit-text-stroke-color: rgb(0, 0, 0); -webkit-text-stroke-width: initial; min-height: 12px;" class=""><span style="font-kerning: none" class=""></span><br class=""></div><div style="margin: 0px; font-size: 10.8px; line-height: normal; -webkit-text-stroke-color: rgb(0, 0, 0); -webkit-text-stroke-width: initial; min-height: 12px;" class=""><span style="font-kerning: none" class=""></span><br class=""></div><div style="margin: 0px; font-size: 10.8px; line-height: normal; -webkit-text-stroke-color: rgb(0, 0, 0); -webkit-text-stroke-width: initial;" class=""><span style="font-kerning: none" class="">2) Some of the magic in #1 could be eliminated by introducing a new capture type: ‘required’ to specify ‘weak guarded’ captures, allowing the example closure to be written:</span></div><div style="margin: 0px; font-size: 10.8px; line-height: normal; -webkit-text-stroke-color: rgb(0, 0, 0); -webkit-text-stroke-width: initial; min-height: 12px;" class=""><br class=""><span style="font-kerning: none" class=""></span></div></div></blockquote><br class=""></div><div>This has been debated before. I support the idea of a “required” capture specifier but IIRC the core team was not supportive of the idea because it adds another layer of magic on the existing magic (object deallocated magically means your closure never executes).</div><div><br class=""></div><div>Russ</div><br class=""></body></html>