<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Jun 10, 2017, at 2:42 PM, Paul Cantrell 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 class="">Being able to specify things about closure capturing at the API level could do wonders for Siesta — though its problems may be beyond the scope of what’s proposed here (or what’s workable at all).</div><div class=""><br class=""></div><div class="">Siesta exposes this API call:</div><div class=""><br class=""></div><div class=""><div class="">&nbsp; &nbsp;&nbsp;someResource.addObserver(owner: self) { &nbsp;// (1)</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; [weak self] resource, event in</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; …</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; self.bar()</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; …</div><div class="">&nbsp; &nbsp; }</div></div><div class=""><br class=""></div><div class="">…but it’s easy to forget that [weak self], and because of Siesta’s observer ownership rules:</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp;&nbsp;<a href="http://bustoutsolutions.github.io/siesta/guide/memory/" class="">http://bustoutsolutions.github.io/siesta/guide/memory/</a></div><div class=""><br class=""></div><div class="">…omitting it creates a retain cycle. This same problem also makes this otherwise lovely pattern untenable:</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp; someResource.addObserver(owner: self, closure: self.fooUpdated) // (2)</div><div class=""><br class=""></div><div class="">To solve this problem, addObserver would need to be able to specify that the object passed as the owner should be weakly captured by the closure. It’s just that one specific •owner• object; everything else should be captured as usual. So it’s not a property of the closure itself, either in the type system or as an argument attribute; it’s a relationship between the closure and other args. Ouch!</div></div></div></blockquote><br class=""></div><div>One way to allow the closure's caller to control the memory management of a value in the closure is to make that value a parameter of the closure rather than a capture.</div><div><br class=""></div><div>In this example addObserver() could store the owner in a weak variable and pass it to the closure when called.</div><div><br class=""></div><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;"><div class=""><div class="">&nbsp; &nbsp; someResource.addObserver(owner: self) {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; owner, resource, event in</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; …</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; owner.bar()</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; …</div><div class="">&nbsp; &nbsp; }</div></div></div><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;"><div class=""><div class=""><br class=""></div><div class=""><br class=""></div><div class="">--&nbsp;</div><div class="">Greg Parker &nbsp; &nbsp; <a href="mailto:gparker@apple.com" class="">gparker@apple.com</a>&nbsp; &nbsp; &nbsp;Runtime Wrangler</div><div class=""><br class=""></div><div class=""><br class=""></div></div></div></div></body></html>