<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 Jul 6, 2016, at 10:31, Xi Ge <<a href="mailto:xi_ge@apple.com" class="">xi_ge@apple.com</a>> 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;"><br class="Apple-interchange-newline"><br class="Apple-interchange-newline"><br class="Apple-interchange-newline"></div><br 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;"><div 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;" class=""><blockquote type="cite" class=""><div class="">On Jul 6, 2016, at 9:39 AM, Jordan Rose <<a href="mailto:jordan_rose@apple.com" class="">jordan_rose@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" 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;"><blockquote type="cite" class=""><div class=""><br class="Apple-interchange-newline">On Jul 5, 2016, at 21:29, Xi Ge <<a href="mailto:xi_ge@apple.com" class="">xi_ge@apple.com</a>> 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 <<a href="mailto:jordan_rose@apple.com" class="">jordan_rose@apple.com</a>> 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 <<a href="mailto:swift-dev@swift.org" class="">swift-dev@swift.org</a>> 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 <<a href="mailto:swift-dev@swift.org" class="">swift-dev@swift.org</a>> 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 </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; </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. 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;">]) { <#code#> }</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: { <#code#> })</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 of the former. Any other contexts in your mind?</span></div></blockquote><br class=""></div><div class="" 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;">For once I<span class="Apple-converted-space"> </span><i class="">don’t</i> 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 class="" 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;"><br class=""></div></div></blockquote><div class=""><br class=""></div><div class="">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></div></blockquote><br class=""></div><div>I don't think that's a rule that's universally agreed on. I use trailing closures for pretty much everything except when there are multiple closure arguments. Erica and others use them for imperative code only. Some people don't use them at all, maybe because they want to preserve the argument label.</div><div><br class=""></div><div>We could try to enforce a universal style here, but that's a direction we need to consciously decide to go in; it's not just clean-up of our existing model. Additionally, we'd then have to come up with an importer rule for deciding which closures are trailing in imported APIs, and allow API owners to control that.</div><div><br class=""></div><div>I do see that it's not out of line for API authors to be able to control this, but I think we should actually design such a thing properly, and we can do that at any time as long as it's just warnings or a separate style checker.</div><div><br class=""></div><div>Jordan</div><br class=""></body></html>