[swift-evolution] Deprecating Trailing Closures

Kurt Werle kurt at circlew.org
Thu Mar 24 09:18:34 CDT 2016

Coming from ruby, I'm quite fond of trailing closures.  I couldn't really
give you a concrete reason why - putting them in the ()'s really isn't that
big a deal.  But I'll say that I move them outside every single time...

I will say that your examples are the most trivial possible and that the
more complex the closure (describing context variables and return types,
throws, etc) the uglier it seem to me to put it inside parens.

On Thu, Mar 24, 2016 at 6:57 AM, 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.
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

kurt at CircleW.org
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160324/d62f06f5/attachment.html>

More information about the swift-evolution mailing list