<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=""><div class="">I like it. Accidental capture of a variable is probably one of the primary causes of retain cycles in modern Swift code. Requiring the capture to be explicit would take a lot of the surprise out of it and force the developer to think about the capture semantics.</div><div class=""><br class=""></div><div class="">+1.</div><div class=""><br class=""></div><div class="">Charles</div><br class=""><div><blockquote type="cite" class=""><div class="">On Jun 26, 2016, at 2:10 PM, Christopher Kornher 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=""><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.&nbsp;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 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="">I have found that Swift’s capture lists and rules are a bit of a mystery to many experienced developers, even though Swift’s closure capture rules are very similar to those of Objective-C. Capture lists are probably thought of as opaque incantations by many new Swift developers if they are aware of them at all. Capture lists should, ideally, not be needed for sensible and safe default behavior.</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="">This discussion is iOS / OS X centric and uses terms from those domains, but these issues should be applicable to almost any codebase that uses closures capturing object references.</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="">Capture lists are required by the fact that object references are captured as `strong` by default, often leading to strong reference cycles and memory leaks.</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’&nbsp;</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=""><span style="font-kerning: none" class="">Many examples of using closures capture self as&nbsp;`unowned`. Often, this pattern does not scale well beyond simple examples. iOS and MacOS applications with dynamic UIs, for example, switch between numerous views and view controllers. These objects are dereferenced and reclaimed when they are no longer needed. Closures capturing these objects as `unowned` crash when the references are accessed.</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="">Unfortunately, ‘unowned’ captures are tempting because they eliminate `guard` and `if let` constructs and avoid littering code with optional unwrapping. They are also slightly more performant, but this difference is probably negligible in most application 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="">Capturing escaping object references as `unowned` is only safe when object lifetimes are perfectly understood. In complex systems, it is difficult to predict execution order. Even if object lifetimes are perfectly understood when code is originally written, seemingly innocuous changes to complex systems can negate original assumptions.</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="">For these reasons, I believe that capturing object references as `unowned` should be considered an advanced optimization technique.</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="">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 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="">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=""><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 closure defined in:</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="">```</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="">class ClosureOwner2 {</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="">&nbsp; &nbsp; var aClosure: (() -&gt; Void)?</span></div><p 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="">&nbsp;&nbsp; &nbsp;</span></p><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="">&nbsp; &nbsp; func aMethod() {</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="">&nbsp; &nbsp; &nbsp; &nbsp; aClosure = { [weak self] in</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="">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self?.someOtherMethod()</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="">&nbsp;&nbsp; &nbsp; &nbsp; }</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="">&nbsp; &nbsp; }</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="">&nbsp; &nbsp; func someOtherMethod(){}</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=""><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="">would normally be written as:&nbsp;</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="">```</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="">&nbsp; &nbsp; &nbsp; &nbsp; aClosure = {</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="">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self?.someOtherMethod()</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="">&nbsp; &nbsp; &nbsp; &nbsp; }</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=""><span style="font-kerning: none" class="">Closures that can be optimized to safely capture object references as `unowned` can use the current syntax.</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="">Swift 2 closure without explicit capture lists for object references will not compile.</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="">Capturing strong object references can be very useful in certain circumstances and have a straightforward syntax:</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="">```</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="">&nbsp; &nbsp; &nbsp; &nbsp; aClosure = { [strong self] in</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="">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.someOtherMethod()</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="">&nbsp; &nbsp; &nbsp; &nbsp; }</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; 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="">Alternatives / Modifications / Improvements(?):</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="">1) Closures with object references could be simplified further by implicitly including ‘let’ guards for all object references:&nbsp;</span></div><p 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="">&nbsp;</span></p><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="">&nbsp; &nbsp; &nbsp; &nbsp; aClosure = {</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="">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // This is included implicitly at the top of the closure:</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 class="Apple-tab-span" style="white-space:pre">        </span>// guard let strongSelf = self else { return }</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="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /*strongSelf*/ self.someOtherMethod()</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 class="Apple-tab-span" style="white-space:pre">        </span>print( “This will not appear when self is nil.” )</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=""><span class="Apple-tab-span" style="white-space:pre">        </span>… other uses of strongSelf…</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="">&nbsp; &nbsp; &nbsp; &nbsp; }</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="">This would have the effect of making the execution of the closure dependent upon the successful unwrapping of all of its object references. Object references that are not required to unwrap successfully can be captured as `weak’ if desired.&nbsp;</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; 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:&nbsp; ‘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=""><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="">```</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="">&nbsp; &nbsp; &nbsp; &nbsp; aClosure = { [required self] in</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="">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.someOtherMethod()</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 class="Apple-tab-span" style="white-space:pre">        </span>print( “This will not appear when self is nil.” )</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 class="Apple-tab-span" style="white-space:pre">        </span>print( “This is not the default behavior and the reason for this is clearly stated.” )&nbsp;</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="">&nbsp; &nbsp; &nbsp; &nbsp; }</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=""><span style="font-kerning: none" class="">This reduces the amount of code required, but may increase the cognitive burden over using the current syntax.</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="">`required` is called `guard` in the “Simplified notation” proposal: <a href="https://gist.github.com/emaloney/d34ac9b134ece7c60440" class=""><span style="-webkit-font-kerning: none;" class="">https://gist.github.com/emaloney/d34ac9b134ece7c60440</span></a></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="">This proposal will differ from the “Simplified notation” proposal in that all object references would be captured as `weak` by default in all closures.</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="">Summary</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=""><span style="font-kerning: none" class="">Closures with objects references occur frequently in Swift code and the use of closures is probably only going to increase. Current capture list rules are not developer friendly and force developers to deal with subtle asynchronous memory management issues. This increases the cognitive burden particularly for new developers.</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 should be safe and straightforward by default.</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="">Enhancement #1 without #2 would probably be the easiest option for new developers and result the smallest code size. The question is: is it too “magical” and are the changes in execution behavior going to be significant in practice?</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 rules for closure object references with enhancement #1 can be stated succinctly:</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="">By default:</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>
<ol style="list-style-type: lower-alpha" class="">
<li 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-size: 12px; line-height: normal;" class=""></span><span style="font-kerning: none" class="">Closures do not affect reference counts of the objects that they reference.</span></li>
<li 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-size: 12px; line-height: normal;" class=""></span><span style="font-kerning: none" class="">All object references used within a closure must unwrap successfully for the closure to execute.</span></li>
</ol><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="">I believe that these are safe, sensible and understandable rules that will eliminate the need for capture lists for many closures. What do you think?</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; min-height: 12px;" class=""><span style="font-kerning: none" class=""></span><br class=""></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>