[swift-evolution] Deprecating Trailing Closures

Howard Lovatt howard.lovatt at gmail.com
Thu Mar 24 16:08:56 CDT 2016


I use trailing closures all the time because I find the brackets too noisy,
like ; at the end of a line is too noisy. The sort of code I use is:

    let foo = myArray
        .filter { $0 & 1 == 1 }
        .map { $0 + 1 }
        .reduce(0) { $0 + $1 }

On Friday, 25 March 2016, Haravikk via swift-evolution <
swift-evolution at swift.org> wrote:

> When I started using Swift I was initially very enthusiastic about
> trailing closures, but I’ve actually kind of gone off them somewhat and I’d
> like to discuss why.
>
> Firstly, here are two ways to write a common example using the .map()
> method:
>
> let foo = myArray.map { $0 + 1 }
> let foo = myArray.map({ $0 + 1 })
>
> It’s tough to say that the first form is any neater than the second, other
> than the second having more brackets. However, the first form is somewhat
> ambiguous, as .map in this case looks like a property rather than a method,
> it also visually looks like a statement, followed by a closure rather than
> the two things logically being related. Of course it’s quick to learn that
> these are related, but for consistency I’m starting to now prefer the use
> of parenthesis in almost all cases.
>
> The other advantage of trailing closures is the omission of the label, but
> trailing closures aren’t strictly necessary for this, as we can already
> omit external labels for parameters if we want to, and the example above
> shows that a trailing closure isn’t necessary for this. The only real
> difference is that the trailing closure form makes a label optional,
> because you can either provide the closure with label in parenthesis (if
> the label is required) or omit it by trailing, like so:
>
> something.someMethod(foo: 1, predicate: { $0 < $1})
> something.someMethod(foo: 1) { $0 < $1}
>
> However this kind of arbitrarily makes the following impossible:
>
> something.someMethod(foo: 1, { $0 < $1 })
>
> With this in mind it seems to me that we might be better served by the
> ability to make external labels optional, as this would allow us to be just
> as succinct, while being completely clear about what is being passed into
> this method.
>
>
> The only real remaining advantage that I see to trailing closures is the
> ability to define pseudo language constructs, for example:
>
> func repeatUntilEmpty<C:CollectionType>(collection:C, @noescape _ body:()
> throws -> Void) rethrows { while !collection.isEmpty { body() } }
> repeatUntilEmpty(myArray) {
> /* Do something over and over until myArray is empty */
> }
>
> Which I think is a pretty uncommon type of structure, but could be useful
> in some specialised situations. To support this though we could easily use
> a new @trailing attribute instead to indicate that the closure can be used
> in this way. My example isn’t very good as I can’t think of a case that
> really, really needs this, but I think they’re probably out there.
>
>
> To summarise, having come down off my initial enthusiasm for trailing
> closures I’m not sure that they really add that much syntactically,
> especially in the most common cases, while actually being a little
> ambiguous looking and adding inconsistency to the language. I think they
> should remain for the less common cases that can really benefit from them,
> but as a feature that is opted into, so that we can go for consistency by
> default.
>
> I’m interested to hear other people’s thoughts.
>


-- 
-- Howard.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160325/09b7bc26/attachment.html>


More information about the swift-evolution mailing list