<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 27, 2016, at 2:51 PM, Russ Bishop 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=""><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=""><blockquote type="cite" class=""><div class=""><br class="Apple-interchange-newline">On Jun 27, 2016, at 12:35 AM, Christopher Kornher &lt;<a href="mailto:ckornher@me.com" class="">ckornher@me.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><br class=""><blockquote type="cite" class="">On Jun 26, 2016, at 4:25 PM, Russ Bishop &lt;<a href="mailto:xenadu@gmail.com" class="">xenadu@gmail.com</a>&gt; wrote:<br class=""><br class=""><br class=""><blockquote type="cite" class="">On Jun 26, 2016, at 12:10 PM, Christopher Kornher via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><br 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&nbsp;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&nbsp;start writing useful and correct code.<br class=""><br 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&nbsp;altogether by default. I am very interested in hearing others’ opinions as to whether the benefits outweigh the costs of various options.<br class=""></blockquote><br class="">The problem is that strong reference capture is probably the far more common case.<br class=""></blockquote><br class="">Strong reference capture has not been more common in carefully written code in my experience. Swift is starting to be used for many different problem&nbsp;domains, so your experience may be different. Any examples of real-world code would be greatly appreciated.<br class=""></div></div></blockquote><div class=""><br class=""></div><div class="">In my experience reference cycles are almost always caused by capturing self strongly.</div><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><br class="">Sometimes closures contain the only references to objects, but this is not common in code that I have seen. It would be extremely rare for strong references to&nbsp;be required for all the references in closure with multiple references (the current default behavior). Long closures can reference many objects and it is all too&nbsp;easy to leave a reference out of the capture list and create a reference cycle.&nbsp;I believe that this pattern should be called-out (see below).<br class=""><br class="">Strong references are occasionally needed to ensure operations are performed when objects would otherwise be reclaimed, but I have not seen many of&nbsp;these cases. This pattern could be more common in other frameworks. I believe that this pattern should be called-out (see below).<br class=""><br class="">Multiple capture rules for closures can be supported if desired. The ```[required…``` capture qualifier in the original email is one way todo this. The question&nbsp;mark could be used in a way analogous to `try?` to identify closures using the proposed rules:&nbsp;<br class=""><br class="">```let a:()-&gt;Void = {…}?```<br class="">or&nbsp;<br class="">``` let a:()-&gt;Void = ?{…}```<br class="">etc.<br class=""><br class="">This would obviously add more complexity but would still be an improvement, I believe.<br class=""></div></div></blockquote><div class=""><br class=""></div><div class="">Possibly, though this inevitably ends up with the C++ lambda rules more or less. To put it another way, why would Swift introduce a new way of handling this instead of just requiring all closures to specify whether they want strong default, weak default, or whatever and completely eliminate any automatic behavior? Unfortunately that makes creating closures much more annoying.</div></div></div></blockquote><div><br class=""></div><div>I took a quick look at C++ capture lists. Yeah, we don’t want those. But another default behavior for captures does make sense for Swift I think. More to come.</div><br class=""><blockquote type="cite" class=""><div class=""><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=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><br class=""><br class=""><blockquote type="cite" class="">If you wanted to say that @noescape closures capture references strongly by default, while escaping closures capture them weakly by default that may be&nbsp;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&nbsp;that @noescape captures strongly, escaping captures self weak by default but other objects strongly… of course that would have even worse cognitive&nbsp;overhead.)<br class=""></blockquote><br class="">I did consider treating self differently, but this leads to some very strange cases when delegation, factories and other patterns are considered.&nbsp;<br class=""><br class="">This email was implicitly referring to escaping uses of closures. The same closure can be used as escaping or non-escaping. The Swift documentation states:<div class=""><br class=""></div><div class="">&nbsp;"<i class="">Marking a closure with&nbsp;@noescape&nbsp;lets the compiler make more aggressive optimizations because it knows more information about the&nbsp;closure’s lifespan.</i>"<br class=""><br class="">@noescape is essentially a hint to the compiler. Optimizers would be free to use strong or unowned references if they can determine&nbsp;that it is safe to do so without altering behavior.&nbsp;<br class=""></div></div></div></blockquote><div class=""><br class=""></div><div class="">The majority of all closures are passed to non-escaping functional methods like map, filter, etc.</div></div></div></blockquote><div><br class=""></div><div>&nbsp;Not in the iOS programming that I do most of the time, but I am sure that the is often the case for other types of development. I rarely use object references in @noescape closures, but styles differ.&nbsp;</div><br class=""><blockquote type="cite" class=""><div class=""><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=""><div class=""> I don’t see how having them default to weak is a good thing in any capacity.</div></div></div></blockquote><div><br class=""></div><div>After thinking about it, i agree. @noescape usages of closures should capture strongly.&nbsp;</div><br class=""><blockquote type="cite" class=""><div class=""><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=""><div class="">Once we agree on that anything else but strong capture by default will by necessity introduce a cognitive burden.</div></div></div></blockquote><div><br class=""></div>When closures are used to define UI behaviors, capturing weak is a very reasonable default. When GUI elements go away, the reason for the behaviors usually goes with them. This is the context that inspired this.&nbsp;<br class=""><div><br class=""></div><blockquote type="cite" class=""><div class=""><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=""><div class=""><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><br class=""><blockquote type="cite" class=""><br class="">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&nbsp;default), or you require everyone to spam their closures with explicit capture annotations even if there’s a default “capture everything strongly” variant (see&nbsp;C++ lambdas).<br class=""></blockquote><br class="">Yes, we are discussing tradeoffs. Writing correct code with closures will always require care.I believe that is is better to have safe, leak free code by default&nbsp;than not. I also believe that capturing strong references by default can probably lead to at least as many unexpected behaviors as capturing weak references. I&nbsp;don’t think that many developers would expect, for example, to see zombie view controllers that have not been associated with an active view hierarchy for&nbsp;weeks because a closure is holding on to a strong reference.<br class=""></div></div></div></blockquote><div class=""><br class=""></div><div class="">I don’t agree that weak by default would equal “safe, leak free”. It might be leak-free but it certainly isn’t necessarily safe. In the face of concurrency you can’t overlook the “half executed” situation of consecutively doing “self?.xyz(); self?.abc()”. Most programmers will assume both xyz() and abc() execute or neither execute but that simply isn’t the case. By making weak the default capture this existing problem is greatly exacerbated.</div><div class=""><br class=""></div><br class=""></div><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="">Russ_______________________________________________</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=""><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="">swift-evolution mailing list</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=""><a href="mailto:swift-evolution@swift.org" 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="">swift-evolution@swift.org</a><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=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" 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="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></div></blockquote></div><br class=""></body></html>