[swift-evolution] [Review] SE-0056: Allow trailing closures in `guard` conditions

Xiaodi Wu xiaodi.wu at gmail.com
Mon Apr 4 11:28:38 CDT 2016

On Mon, Apr 4, 2016 at 11:18 AM, Haravikk via swift-evolution
<swift-evolution at swift.org> wrote:
>> On 4 Apr 2016, at 15:49, Jeremy Pereira <jeremy.j.pereira at googlemail.com> wrote:
>>> On 3 Apr 2016, at 17:20, Haravikk via swift-evolution <swift-evolution at swift.org> wrote:
>>> Although I use trailing closures a lot less now, I think I’m a +1 anyway for consistency’s sake.
>>> I actually really like the idea of having trailing keywords in loops and if statements, these needn’t be required (except where a trailing closure is used) but for example it means I could do a fully natural language loop like:
>>>      for eachValue in theValues do { … }
>> This is actually kind of bizarre. Here we are trying to invent new syntax so that the trailing closure can be used in if/while conditions and for sequences. However, there is already a perfectly good syntax for putting closures in these positions: put the closure in the parentheses of the function call. Are people really so desperate to use trailing closures everywhere that we have to add new keywords to the language? I don’t think they are.
> While I kind of agree (and personally prefer the use of parenthesis in most places anyway) it’s an inconsistency to be unable to use them I think. While It’s understandable from a parsing/ambiguity perspective, it’s not really intuitive.

I think it's quite consistent. Trailing closures must be trailing.
Interpret that to mean that it must be the last thing surrounded by
braces, not just the last closure. If a function takes two closures,
only the last can be written with trailing closure syntax. In the
context of a control statement, if a block of code surrounded by
braces follows the closure, the closure cannot be written in trailing
closure syntax. By your argument for "consistency," all closures
should be allowed to be written in trailing syntax, so that for `func
foo(_: Int, _: () -> (), _: () -> ())`, I should be able to write
`func foo(2) { /* code */ } { /* code */ }`. I don't think we need
that level of "consistency."

>>> I like the consistency of every block having a kind of type (do, else, defer, catch etc.).
>> That is a rabbit hole down which you probably shouldn't go. If we go down the route of blocks having a “type”, the current situation in Swift becomes somewhat inconsistent. I would argue that the `else` block on a `guard` is of a different type to the `else` block on an `if`. If anything, the `else` block of an `if` is closer to the `then` block. Also, would you allow the `do` block in a `for` or `while` to have a `catch` block following it? If not, then these blocks are different to the  existing bare `do` block.
> Actually that’s not quite what I meant by “type”; while there is a case to be made for unifying these more (else and catch on loops for example) I just meant more along the lines that “do” would always group the main branch, “else” indicates an alternative path if a condition isn’t met and so-on. For the short term however this would just be a case of allowing do on the end to eliminate ambiguity and thus allow trailing closures, but in the long term it could be explored further.

More information about the swift-evolution mailing list