[swift-dev] Fixit for trailing closures

Xi Ge xi_ge at apple.com
Wed Jul 6 12:31:08 CDT 2016





> On Jul 6, 2016, at 9:39 AM, Jordan Rose <jordan_rose at apple.com> wrote:
> 
>> 
>> On Jul 5, 2016, at 21:29, Xi Ge <xi_ge at apple.com <mailto:xi_ge at apple.com>> wrote:
>> 
>>> 
>>> On Jul 5, 2016, at 8:31 PM, Jordan Rose <jordan_rose at apple.com <mailto:jordan_rose at apple.com>> wrote:
>>> 
>>>> 
>>>> On Jul 5, 2016, at 17:19, Ben Langmuir via swift-dev <swift-dev at swift.org <mailto:swift-dev at swift.org>> wrote:
>>>> 
>>>>> 
>>>>> On Jul 5, 2016, at 4:34 PM, Xi Ge via swift-dev <swift-dev at swift.org <mailto:swift-dev at swift.org>> wrote:
>>>>> 
>>>>> Hi Swift-devs,
>>>>> I have tried to add a fixit to help developers using trailing closures more, motivated by my observation during WWDC that some developers 
>>>>> 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; 
>>>>> therefore users should adopt trailing closures whenever doing so introduces no ambiguity.
>>>>> 
>>>>> Fixits can enhance the discoverability of trailing closures by identifying misuses and by transforming users’ code automatically. However, adding the fixit introduces new issues:
>>>>> 
>>>>> 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.
>>>>> 
>>>>> Issue 2: Ambiguity checking should be exhaustive. We have several known situations when non-trailing closures cannot be convert to trailing closures, including:
>>>>> 	
>>>>> Trailing closures are followed by other brackets, e.g., “if foo({}) {}” cannot be converted to “if foo {} {}”.
>>>>> 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.
>>>>> 
>>>>> So Swift-devs, is the warning worth adding? If yes, are there other situations of ambiguity that are not covered?
>>>>> 
>>>>> Thanks for your feedback!
>>>>> Xi
>>>>> 
>>>> 
>>>> -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.
>>>> 
>>>> My biggest concern is that it’s not always obvious what the closure is used for.  The argument label can help with this:
>>>> 
>>>> [1].lexicographicallyPrecedes([0]) { <#code#> }
>>>> [1].lexicographicallyPrecedes([0], isOrderedBefore: { <#code#> })
>>> 
>>> 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.
>>> 
>>> (Motivation: Another case where I prefer not using a trailing closure is when there are other closure arguments in the call.)
>>> 
>> 
>> 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”.
>> “lexicographicallyPrecedes” is a good example of the later while "DispatchQueue.async(execute:)” is of the former. Any other contexts in your mind?
> 
> For once I don’t 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.
> 

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?
Xi

> Jordan

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-dev/attachments/20160706/908dcc51/attachment.html>


More information about the swift-dev mailing list