A simple solution to the ambiguity problem of multiple ātrailingā closures is to simply require that they start on the same line as the preceding closure, after the }. e.g.:
// This is a single call to when(_:_:otherwise:)
when (2 < 3) { doSomething() } otherwise { do SomethingElse() }
// This is two independent calls, one to when(_:_:), the other to otherwise(_:).
when (2 < 3) { doSomething() }
otherwise { do SomethingElse() }
Or if you prefer:
// Again, unambiguously all a single statement & function call.
when (2 < 3) {
doSomething()
} otherwise {
doSomethingElse()
}
// Two independent statements & function calls (though it would arguably
// be stylistically superior to put a blank line between them, for further clarity).
when (2 < 3) {
doSomething()
}
otherwise {
doSomethingElse()
}
This builds on the notion that Swift implicitly uses line returns to signal the end of a statement, in lieu of an explicit semicolon. It also still leaves you the option of using an explicit semicolon to differentiate the scenario where you really do mean to start a second statement, not pass an additional, optional argument.
The compromise it makes is that it rules out the style choice of placing line-returns after the }, but I feel thatās fine since thatās atypical style in Swift, and if it comes down to a choice itās more in line with idiomatic Swift than requiring special look-ahead parsing, semicolons on argument names, etc. It also ensures you can precisely mimic existing control flow syntax, if thatās your thing.
Mechanism aside, and thinking about whether Swift should adopt such functionality⦠I am intrigued by this. It does have some obvious concerns that would need assuaging, such as that it wonāt end up being a C++ templates situation where people get carried away and produce confusing pseudo-DSLs and generally over-designed monstrosities. Iām also not all that interested in the intellectual amusement of replicating existing control flow structures by other means - thatās cute, but doesnāt seem practical.
However, I am interested in it being a cleaner way to express the very common patterns involved in using futures & promises, asynchronous / conditional control flow, and āN+1ā call sequences (i.e. call this first closure for each of the N iterations / things / whatever, then this second closure once at the end).
It must be noted however that, unless variadic arguments of closures are also supported, this doesnāt seem to scale as well for ⦠}.andThen { ⦠}⦠sort of things.