<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 22 May 2016, David Hart 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="">If the design team is very serious about not integrating optional warnings, then I don’t think it is a huge bother to implement think in linters like SwiftLint is doing.</div></div></blockquote></div><br class=""><div class="">I'm fine with the way SE-0009 was decided but I think the review left one consideration for linters unexplored: How to be explicit about what's captured by a closure if the coding style enforced by a linter involves using `<font face="Menlo" class="">self.</font>` everywhere?</div><div class=""><br class=""></div><div class="">There were (are) basically two reasons for keeping `<font face="Menlo" class="">self.</font>` implicit the way it is:</div><div class=""><br class=""></div><div class=""><b class="">Reason </b><b class="">1.</b> It keeps noise level down. E.g. computed properties often read better this way:</div><div class=""><br class=""></div><div class=""><font face="Menlo" class=""> <b class="">var</b> area: Double {</font></div><div class=""><font face="Menlo" class=""> <b class="">return</b> width * height</font></div><div class=""><font face="Menlo" class=""> <font color="#919191" class="">// rather than: 'self.width * self.height'</font></font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><br class=""></div><div class=""><b class="">Reason 2.</b> It makes the capturing of `<font face="Menlo" class="">self</font>` explicit, because `<font face="Menlo" class="">self.</font>` is only required in escaping closures and thus the capturing expressions require thinking when writing code and also stand out when reading code.</div><div class=""><br class=""></div><div class="">I think those are good reasons. But then, the language rules don't really favour the other coding style where the `<font face="Menlo" class="">self.</font>` prefix is used throughout, even if it *<i class="">can*</i> be enforced by a linter:</div><div class=""><br class=""></div><div class=""><b class="">Example 1</b>. There's no other way (but using the `<font face="Menlo" class="">self.</font>` prefix) to indicate that `<font face="Menlo" class="">self</font>` should be retained by a closure:</div><div class=""><br class=""></div><div class=""><font face="Menlo" class=""> <b class="">self</b>.prepareWork()</font></div><div class=""><font face="Menlo" class=""> queue.async { [<b class=""><font color="#ff2600" class="">self</font></b>] <b class="">in</b></font></div><div class=""><font face="Menlo" class=""> <font color="#ff2600" class="">// <b class=""> ^</b></font></font></div><div class=""><font face="Menlo" class=""> <font color="#ff2600" class="">// <b class="">error:</b> Expected 'weak', 'unowned', or no</font></font></div><div class=""><font face="Menlo" class=""><font color="#ff2600" class=""> // specifier in capture list</font></font></div><div class=""><font face="Menlo" class=""> <b class="">self</b>.doTheWork()</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><br class=""></div><div class=""><b class="">Example 2.</b> There's currently no way to mark when an escaping closure is intended to <b class="">**not**</b> capture any other references but those explicitly listed:</div><div class=""><br class=""></div><div class=""><font face="Menlo" class=""> queue.async { [bar] <b class="">in</b></font></div><div class=""><font face="Menlo" class=""> <b class="">if</b> bar.isAdjustable {</font></div><div class=""><font face="Menlo" class=""> <font color="#ff2600" class="">baz</font>.adjust()</font></div><div class=""><span style="font-family: Menlo;" class=""> }</span></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><div class=""><font face="Menlo" class=""> </font><span style="color: rgb(145, 145, 145); font-family: Menlo;" class="">// Meant 'bar', but compiler didn't alert!</span></div></div><div class=""><span style="color: rgb(145, 145, 145); font-family: Menlo;" class=""><br class=""></span></div><div class="">So I think it would be a good idea to adjust the capture list syntax a bit:</div><div class=""><br class=""></div><div class=""><b class="">Suggestion 1.</b> Allow capture lists to explicitly state that they capture `<font face="Menlo" class="">self</font>` strongly by spelling it out with no weak/unowned specifier, i.e. `<font face="Menlo" class="">[self]</font>`.</div><div class=""><br class=""></div><div class=""><b class="">Suggestion 2.</b> Add a succinct way to indicate that the capture list is <i class="">*comprehensive*</i>, i.e. that implicitly capturing other variables from the local scope is an error. (Capturing variables from the file scope should be allowed though, I reckon.) The syntax for this could be e.g. postfixing the capture list brackets with the exclamation mark `<font face="Menlo" class="">!</font>`:</div><div class=""><br class=""></div><div class=""><span style="font-family: Menlo;" class=""> queue.async { [service]! </span><b style="font-family: Menlo;" class="">in</b></div><div class=""><font face="Menlo" class=""> service.</font><span style="font-family: Menlo;" class="">handleTask</span><font face="Menlo" class="">(<b class=""><font color="#ff2600" class="">self</font></b>.task)</font></div><div class=""><span style="font-family: Menlo;" class=""> </span><font color="#ff2600" style="font-family: Menlo;" class="">// ^</font></div><div class=""><font color="#ff2600" style="font-family: Menlo;" class=""> // <b class="">error:</b> Implicit capture of 'self' in closure</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><div class=""><font face="Menlo" class=""> queue.async { [service, <b class="">self</b>]! <b class="">in</b></font></div><div class=""><font face="Menlo" class=""> service.</font><span style="font-family: Menlo;" class="">execute</span><font face="Menlo" class="">(<b class="">self</b>.task) <font color="#919191" class="">// ok</font></font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class=""> queue.async { [service, task = <b class="">self</b>.task]! <b class="">in</b></font></div><div class=""><font face="Menlo" class=""> service.</font><span style="font-family: Menlo;" class="">execute</span><font face="Menlo" class="">(task) <font color="#919191" class="">// also ok; didn't capture 'self'</font></font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""></div><div class=""><font face="Menlo" class=""> queue.async { [bar]! <b class="">in</b></font></div><div class=""><font face="Menlo" class=""> <b class="">if</b> bar.isAdjustable {</font></div><div class=""><font face="Menlo" class=""> <font color="#ff2600" class="">baz</font>.adjust()</font></div><div class=""><font face="Menlo" class=""> <font color="#ff2600" class="">// ^</font></font></div><div class=""><font face="Menlo" class=""><font color="#ff2600" class=""> // <b class="">error:</b> Implicit capture of 'baz' in closure</font></font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class=""> }</font></div></div><div class=""><br class=""></div><div class="">With these two changes, the coding style choice of what to use the `<font face="Menlo" class="">self.</font>` prefix for would be better supported both ways, and no optional warnings would be needed. A linter could then require capturing `<font face="Menlo" class="">self</font>` explicitly where it's used inside an escaping block. Myself, I wouldn't use comprehensive capture lists all the time but there have been a few cases where it would've been useful to prevent mistakenly capturing anything that could create a retain cycle.</div><div class=""><br class=""></div><div class="">Any thoughts? Would an idea like this help any of the people who started this mailing list thread—that is, with the aid of a respectively configured linter of course?</div><div class=""><br class=""></div><div class="">— Pyry</div><div class=""><br class=""></div></body></html>