<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 class=""><br class="Apple-interchange-newline"><br class="Apple-interchange-newline">

</div>
<br class=""><div><blockquote type="cite" class=""><div class="">On Jul 6, 2016, at 9:39 AM, Jordan Rose &lt;<a href="mailto:jordan_rose@apple.com" class="">jordan_rose@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class=""><br class="Apple-interchange-newline">On Jul 5, 2016, at 21:29, Xi Ge &lt;<a href="mailto:xi_ge@apple.com" class="">xi_ge@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><blockquote type="cite" class=""><div class=""><br class="Apple-interchange-newline">On Jul 5, 2016, at 8:31 PM, Jordan Rose &lt;<a href="mailto:jordan_rose@apple.com" class="">jordan_rose@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><blockquote type="cite" class=""><div class=""><br class="Apple-interchange-newline">On Jul 5, 2016, at 17:19, Ben Langmuir via swift-dev &lt;<a href="mailto:swift-dev@swift.org" class="">swift-dev@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><blockquote type="cite" class=""><div class=""><br class="Apple-interchange-newline">On Jul 5, 2016, at 4:34 PM, Xi Ge via swift-dev &lt;<a href="mailto:swift-dev@swift.org" class="">swift-dev@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><span id="docs-internal-guid-d07b8252-bd62-362d-862c-7fd88323b9e5" class=""><div class="" style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;"><span class="" style="font-size: 14.666666666666666px; font-family: Arial; font-variant-ligatures: normal; font-variant-position: normal; font-variant-numeric: normal; font-variant-alternates: normal; font-variant-east-asian: normal; vertical-align: baseline; white-space: pre-wrap;">Hi Swift-devs,</span></div><div class="" style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;"><span class="" style="font-size: 14.666666666666666px; font-family: Arial; font-variant-ligatures: normal; font-variant-position: normal; font-variant-numeric: normal; font-variant-alternates: normal; font-variant-east-asian: normal; vertical-align: baseline; white-space: pre-wrap;">I have tried to add a fixit to help developers using trailing closures more, motivated by my observation during WWDC that some developers&nbsp;</span></div><div class="" style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;"><span class="" style="font-size: 14.666666666666666px; font-family: Arial; font-variant-ligatures: normal; font-variant-position: normal; font-variant-numeric: normal; font-variant-alternates: normal; font-variant-east-asian: normal; vertical-align: baseline; white-space: pre-wrap;">do not even realize that we have such a feature. In my opinion, trailing closures are more concise, and once you get used to it, more readable;&nbsp;</span></div><div class="" style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;"><span class="" style="font-size: 14.666666666666666px; font-family: Arial; font-variant-ligatures: normal; font-variant-position: normal; font-variant-numeric: normal; font-variant-alternates: normal; font-variant-east-asian: normal; vertical-align: baseline; white-space: pre-wrap;">therefore users should adopt trailing closures whenever doing so introduces no ambiguity.</span></div><br class=""><div class="" style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;"><span class="" style="font-size: 14.666666666666666px; font-family: Arial; font-variant-ligatures: normal; font-variant-position: normal; font-variant-numeric: normal; font-variant-alternates: normal; font-variant-east-asian: normal; vertical-align: baseline; white-space: pre-wrap;">Fixits can enhance the discoverability of trailing closures by identifying misuses and by transforming users’ code automatically. However, adding the fixit introduces new issues:</span></div><br class=""><div class="" style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;"><span class="" style="font-size: 14.666666666666666px; font-family: Arial; font-variant-ligatures: normal; font-variant-position: normal; font-variant-numeric: normal; font-variant-alternates: normal; font-variant-east-asian: normal; vertical-align: baseline; white-space: pre-wrap;">Issue 1: The fixit has to be associated with a warning. Adding the warning means we declare wars against convertible non-trailing closures, which is a valid syntax choice by users.</span></div></span></div></div></blockquote><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><span id="docs-internal-guid-d07b8252-bd62-362d-862c-7fd88323b9e5" class=""><br class=""><div class="" style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;"><span class="" style="font-size: 14.666666666666666px; font-family: Arial; font-variant-ligatures: normal; font-variant-position: normal; font-variant-numeric: normal; font-variant-alternates: normal; font-variant-east-asian: normal; vertical-align: baseline; white-space: pre-wrap;">Issue 2: Ambiguity checking should be exhaustive. We have several known situations when non-trailing closures cannot be convert to trailing closures, including:</span></div><p dir="ltr" class="" style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;"><span class="" style="font-size: 14.666666666666666px; font-family: Arial; font-variant-ligatures: normal; font-variant-position: normal; font-variant-numeric: normal; font-variant-alternates: normal; font-variant-east-asian: normal; vertical-align: baseline; white-space: pre-wrap;"><span class="Apple-tab-span" style="white-space: pre;">        </span></span></p><ol class="" style="margin-top: 0pt; margin-bottom: 0pt;"><li dir="ltr" class="" style="list-style-type: lower-alpha; font-size: 14.666666666666666px; font-family: Arial; font-variant-ligatures: normal; font-variant-position: normal; font-variant-numeric: normal; font-variant-alternates: normal; font-variant-east-asian: normal; vertical-align: baseline;"><div class="" style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;"><span class="" style="font-size: 14.666666666666666px; font-variant-ligatures: normal; font-variant-position: normal; font-variant-numeric: normal; font-variant-alternates: normal; font-variant-east-asian: normal; vertical-align: baseline; white-space: pre-wrap;">Trailing closures are followed by other brackets, e.g., “if foo({}) {}” cannot be converted to “if foo {} {}”.</span></div></li><li dir="ltr" class="" style="list-style-type: lower-alpha; font-size: 14.666666666666666px; font-family: Arial; font-variant-ligatures: normal; font-variant-position: normal; font-variant-numeric: normal; font-variant-alternates: normal; font-variant-east-asian: normal; vertical-align: baseline;"><div class="" style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;"><span class="" style="font-size: 14.666666666666666px; font-variant-ligatures: normal; font-variant-position: normal; font-variant-numeric: normal; font-variant-alternates: normal; font-variant-east-asian: normal; vertical-align: baseline; white-space: pre-wrap;">Removing the label of the last closure causes ambiguous function references, e.g. “foo(v: {})” cannot be converted to “foo {}” when “foo(v1: {})” also exists.</span></div></li></ol><br class=""><div class="" style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;"><span class="" style="font-size: 14.666666666666666px; font-family: Arial; font-variant-ligatures: normal; font-variant-position: normal; font-variant-numeric: normal; font-variant-alternates: normal; font-variant-east-asian: normal; vertical-align: baseline; white-space: pre-wrap;">So Swift-devs, is the warning worth adding? If yes, are there other situations of ambiguity that are not covered?</span></div><br class=""><div class="" style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;"><span class="" style="font-size: 14.666666666666666px; font-family: Arial; font-variant-ligatures: normal; font-variant-position: normal; font-variant-numeric: normal; font-variant-alternates: normal; font-variant-east-asian: normal; vertical-align: baseline; white-space: pre-wrap;">Thanks for your feedback!</span></div><div class="" style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;"><span class="" style="font-size: 14.666666666666666px; font-family: Arial; font-variant-ligatures: normal; font-variant-position: normal; font-variant-numeric: normal; font-variant-alternates: normal; font-variant-east-asian: normal; vertical-align: baseline; white-space: pre-wrap;">Xi</span></div><br class=""></span></div></div></blockquote><div class=""><br class=""></div><div class=""><div class="">-1, this feels like a really good tool to have in a code-linter, but not something that we should put in the compiler and prescribe to all our users.</div><div class=""><br class=""></div><div class="">My biggest concern is that it’s not always obvious what the closure is used for. &nbsp;The argument label can help with this:</div><div class=""><br class=""></div><div class=""><div class="" style="margin: 0px; font-size: 13px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures;">[</span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(39, 42, 216);">1</span><span class="" style="font-variant-ligatures: no-common-ligatures;">].lexicographicallyPrecedes([</span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(39, 42, 216);">0</span><span class="" style="font-variant-ligatures: no-common-ligatures;">]) { &lt;#code#&gt; }</span></div></div><div class=""><div class="" style="margin: 0px; font-size: 13px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures;">[</span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(39, 42, 216);">1</span><span class="" style="font-variant-ligatures: no-common-ligatures;">].lexicographicallyPrecedes([</span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(39, 42, 216);">0</span><span class="" style="font-variant-ligatures: no-common-ligatures;">], isOrderedBefore: { &lt;#code#&gt; })</span></div></div></div></div></div></blockquote><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">I strongly agree with Ben. This is a style choice and highly context-dependent. We should not warn about it or produce a fix-it unless specifically requested, and we don’t have any place for such requests today.</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">(Motivation: Another case where I prefer not using a trailing closure is when there are other closure arguments in the call.)</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div></div></blockquote><div class=""><br class=""></div><span class="">I agree with you if by “context-sensitive”, you mean “function-signature-sensitive”; and we can solve that by adding a new attribute on function decls to categorize a function into either “trailing closure preferred” or “inline closure preferred”.</span></div><span class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">“lexicographicallyPrecedes” is a good example of the later while "DispatchQueue.async(execute:)” is&nbsp;of the former. Any other contexts in your mind?</span></div></blockquote><br class=""></div><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">For once I<span class="Apple-converted-space">&nbsp;</span><i class="">don’t</i>&nbsp;think that this is something that makes sense for the API author to control. It should always be legal to replace a named closure with an anonymous closure without any other changes.</div><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div></div></blockquote><div><br class=""></div><div>Isn’t trailing closure more amenable to completion blocks/callbacks than predicates like “isOrderedBefore”. Aren’t API authors the best people to tell the role of the closure?</div><div>Xi</div><br class=""><blockquote type="cite" class=""><div class=""><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">Jordan</div></div></blockquote></div><br class=""></body></html>