<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 <<a href="mailto:antonvmironov@gmail.com" class="">antonvmironov@gmail.com</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 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. This allows an API to require its callers to use a guarded closure. 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? 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. The guarded closure lives until the control releases it. But it becomes a no-op if any of the references captured with a guard are released before that happens. 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. I’ll give it some thought. 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. I wouldn't want `DispatchQueue.async` to take a guarded closure. That API doesn’t contain any semantic content around *why* you dispatched async. 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=""> .debounce(interval: 3.0)</div><div class=""> .map(context: self) { (self, _) in</div><div class=""> return self.searchField.text</div><div class=""> }</div><div class=""> .distinct()</div><div class=""> .onUpdate(context: self) { (self, searchQuery) in</div><div class=""> self.performSearch(query: searchQuery)</div><div class=""> }</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. This is more work for both the library and the client than necessary. It also does not help users avoid an accidental strong reference in the closure. It nudges them not to by offering to thread the context but it doesn’t do anything to prevent it. 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 <<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="">Hi David,<div class=""><br class=""></div><div class="">I just shared a draft proposal to introduce guarded closures last week: <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>. 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. Guarded behavior requires prefixing the contents of the closure with a guard clause that returns immediately if the guard is tripped. This is a property of the closure as a whole, not of an individual capture. For that reason, I decided that allowing a `guard` specifier for an individual capture would be inappropriate. </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. The thread on this proposal was relatively brief. 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 <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> 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=""> { [weak self] in 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=""> guard let strongSelf = self else { return }</span><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class=""> strongSelf.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="">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=""> 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=""> guard let strongSelf = self else { return }</span><br style="font-size:12.8px" class=""><span style="font-size:12.8px" class=""> 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>