<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 Feb 22, 2017, at 5:06 PM, Anton Mironov &lt;<a href="mailto:antonvmironov@gmail.com" class="">antonvmironov@gmail.com</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 class="">-1</div><div class="">I support improvements in this area but I do not think that adding guarded closures will fix the case.</div><div class="">It raises multiple concerns:</div><div class="">- prepending ? to the closure declaration is as forgettable as `[weak self]`</div></div></div></blockquote><div><br class=""></div><div>No, this is why I included the `@guarded` parameter annotation. &nbsp;This allows an API to require its callers to use a guarded closure. &nbsp;Strong references would have to be explicit in the capture list.</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="">- reactive programming often assumes chaining of operations. How guarded closures affect next operations in the chain?</div></div></div></blockquote><div><br class=""></div><div>Can you provide a concrete example of real world code you wrote manually? &nbsp;I will convert it to use guarded closures to show how it is affected.</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="">- the closure must exist until either the control deallocates (source of actions) or self deallocates (destination of actions). Guarded closure will not provide an expected behavior</div></div></div></blockquote><div><br class=""></div><div>Yes they will. &nbsp;The guarded closure lives until the control releases it. &nbsp;But it becomes a no-op if any of the references captured with a guard are released before that happens. &nbsp;This is much like the behavior of the target / action pattern but generalized to support closures.</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="">- managing lifecycle of nested guarded closures could be complex to understand and implement into the language</div></div></div></blockquote><div><br class=""></div><div>I’m glad you brought this up. &nbsp;I’ll give it some thought. &nbsp;If there does turn out to be complexity involved I wouldn’t have a problem prohibiting that.</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="">- why would you consider using @escaping instead of @guarded?</div></div></div></blockquote><div><br class=""></div><div>Because sometimes the right default for a function taking an escaping closure is a strong reference. &nbsp;I wouldn't want `DispatchQueue.async` to take a guarded closure. &nbsp;That API doesn’t contain any semantic content around *why* you dispatched async. &nbsp;It’s not a callback, but instead a way of moving work around.</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=""><br class=""></div><div class="">I personally prefer doing something like this:</div><div class=""><br class=""></div><div class="">```swift</div><div class="">self.button.onAction(forEvents: [.touchUpInside], context: self) { (self, sender, event) in</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>self.performSearch(query: self.searchField.text)</div><div class="">}</div><div class="">```</div><div class=""><br class=""></div><div class="">or</div><div class=""><br class=""></div><div class="">```swift</div><div class="">self.button.actions(forEvents: [.touchUpInside])</div><div class="">&nbsp; &nbsp; .debounce(interval: 3.0)</div><div class="">&nbsp; &nbsp; .map(context: self) { (self, _) in</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; return self.searchField.text</div><div class="">&nbsp; &nbsp; }</div><div class="">&nbsp; &nbsp; .distinct()</div><div class="">&nbsp; &nbsp; .onUpdate(context: self) { (self, searchQuery) in</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; self.performSearch(query: searchQuery)</div><div class="">&nbsp; &nbsp; }</div><div class="">```</div><div class=""><br class=""></div><div class="">This code neither requires an addition of language features nor contains retain cycles. All closures will be released as soon as source or destination deallocates.</div></div></div></blockquote><div><br class=""></div><div>This isn’t too bad but it does require manually threading the context. &nbsp;This is more work for both the library and the client than necessary. &nbsp;It also does not help users avoid an accidental strong reference in the closure. &nbsp;It nudges them not to by offering to thread the context but it doesn’t do anything to prevent it. &nbsp;You can still create a strong reference (event to self) without specifying it in the capture list.</div><div><br class=""></div><div>I think there is a place for a language solution here.</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=""><br class=""></div><div class=""><blockquote type="cite" class=""><div class="">On Feb 22, 2017, at 22:57, Matthew Johnson 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="">Hi David,<div class=""><br class=""></div><div class="">I just shared a draft proposal to introduce guarded closures last week:&nbsp;<a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170213/032478.html" class="">https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170213/032478.html</a>. &nbsp;I think you would find it very interesting.</div><div class=""><br class=""></div><div class="">I considered including a new capture list specifier `guard` in this proposal but decided against it. &nbsp;Guarded behavior requires prefixing the contents of the closure with a guard clause that returns immediately if the guard is tripped. &nbsp;This is a property of the closure as a whole, not of an individual capture. &nbsp;For that reason, I decided that allowing a `guard` specifier for an individual capture would be inappropriate. &nbsp;</div><div class=""><br class=""></div><div class="">Instead, a guarded closure has a guarded by default capture behavior which can be overridden with `weak`, `unowned` or `strong` in the capture list. &nbsp;The thread on this proposal was relatively brief. &nbsp;I plan to open a PR soon after making a few minor modifications.</div><div class=""><br class=""></div><div class="">Matthew</div><div class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Feb 22, 2017, at 2:48 PM, David Hedbor 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 dir="ltr" class=""><span style="font-size:12.8px" class="">Hello,</span><br style="font-size:12.8px" class=""><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class="">(apologies if this got sent twice - gmail and Apple mail seems to confused as to what account the first mail was sent from)</span><br style="font-size:12.8px" class=""><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class="">I’m new to this mailing list, but have read some archived messages, and felt that this would be a reasonable subject to discuss. It’s somewhat related to the recent posts about @selfsafae/@guarded but distinctly different regardless.</span><br style="font-size:12.8px" class=""><br style="font-size:12.8px" class=""><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class="">Problem:</span><br style="font-size:12.8px" class=""><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class="">It’s often desirable not to capture self in closures, but the syntax for doing so adds significant boilerplate code for [weak self] or us unsafe when used with [unowned self]. Typically you’d do something like this:</span><br style="font-size:12.8px" class=""><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class="">&nbsp; { [weak self] in&nbsp; &nbsp; self?.execute() }</span><br style="font-size:12.8px" class=""><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class="">This is simple enough but often doesn’t work:</span><br style="font-size:12.8px" class=""><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class="">{ [weak self] in self?.boolean = self?.calculateBoolean() ]</span><br style="font-size:12.8px" class=""><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class="">This fails because boolean is not an optional. This in turn leads to code like this:</span><br style="font-size:12.8px" class=""><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class="">{ [weak self] in</span><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class="">&nbsp; &nbsp;guard let strongSelf = self else { return }</span><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class="">&nbsp; &nbsp;strongSelf.boolean = self.calculateBoolean()&nbsp; }</span><br style="font-size:12.8px" class=""><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class="">And this is the boilerplate code. My suggestion is to add a syntax that works the same as the third syntax, yet doesn’t require the boilerplate code.</span><br style="font-size:12.8px" class=""><br style="font-size:12.8px" class=""><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class="">Solution:</span><br style="font-size:12.8px" class=""><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class="">Instead of using unowned or weak, let’s use guard/guarded syntax:</span><br style="font-size:12.8px" class=""><br style="font-size:12.8px" class=""><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class="">{ [guard self] in</span><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class="">&nbsp; &nbsp;self.isExecuted = self.</span><span style="font-size:12.8px" class="">onlyIfWeakSelfWasCaptured<wbr class="">()</span><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class="">}</span><br style="font-size:12.8px" class=""><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class="">In essence, guarded self is equivalent to a weak self, that’s captured when the closure is executed. If it was already released at that point, the closure is simply not executed. It’s equivalent to:</span><br style="font-size:12.8px" class=""><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class="">{ [weak self] in</span><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class="">&nbsp; &nbsp;guard let strongSelf = self else { return }</span><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class="">&nbsp; &nbsp;strongSelf.isExecuted = strongSelf.</span><span style="font-size:12.8px" class="">onlyIfWeakSelfWasCa<wbr class="">ptured()</span><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class="">}</span><br style="font-size:12.8px" class=""><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class="">Except with a lot less boilerplate code, while not losing any clarify in what it does.</span><br style="font-size:12.8px" class=""><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class="">Impact / compatibility:</span><br style="font-size:12.8px" class=""><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class="">This is simply additive syntax, and wouldn’t affect any existing code.</span><br class=""></div>
_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></blockquote></div><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=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></blockquote></div><br class=""></div></div></blockquote></div><br class=""></body></html>