EDIT: This is really unintelligible, so I'm reposting a clearer version.
EDIT: I came up with an idea of using metafunctions similar to function builders to represent multiple trailing closures. It is close to the alternative syntax suggested by Chris Lattner, but instead of two types of arguments, it has one type of argument and a function call builder metafunction. Since this effectively would bring us back down to one type of argument through metaprogramming it may be appetizing to more people. I've been appending this as ideas have occurred to me– sorry this post is more of a brain dump. Does anyone else think this is Swifty?
The alternative proposal wouldn't be introducing any new syntax other than white space as a delimiter. Is that the aspect you have an issue with? It would use labels much in the same way as they are used elsewhere. I'm not sure what other Swift feature we would draw inspiration from other then property accessors, but it is a bad idea to copy that design due to it being too easy to introduce ambiguity.
I suppose we could make them look like modifiers if we want them to look like another swift feature. I could get behind the look of this, but I haven't thought this through fully.
EDIT: In fact I find this somewhat appealing because modifiers are normally used along with trailing closures. They would sort of compose visually.
EDIT 2: "." implies chaining or continuation from the previous line similar to view builder modifiers but with a slightly different syntax. It would still look good with indentation removed. "." is used to compose functions in an expression, so I think it could also be used to compose a trailing closure in an expression. I think of it like a metafunction that adds an argument to a function.
EDIT 3: I think this syntax could also be extended to general "trailing arguments". Normally if I have an argument that is big and awkward– like a list, dictionary, or verbose function call, I would set it to a constant variable that only gets used one time inside an expression. With "trailing arguments" it could just be moved inline and I wouldn't need to pollute my local namespace with single use constants. Sub-expressions would need to be in parentheses.
EDIT 4: Maybe unlabeled single trailing closures could optionally be written "array.prefix .: { $0.someProperty }"–a variation of the syntax below–to help with the ambiguity following the call builder metafunction theme.
EDIT 5: For SwiftUI this would essentially be a Function Call Builder inside a View Builder which I think is kind of cool.
UIView.animate(withDuration: 0.7, delay: 1.0)
// Think of this as a metafunction that adds an argument
// to the `animate` call using a function builder pattern.
.animations: {
self.view.layoutIfNeeded()
}
.completion: { finished in
print("Basket doors opened!")
}
// Could remove whitespace when composing:
UIView.animate(withDuration: 0.7, delay: 1.0).animations: { self.view.layoutIfNeeded() }
.completion: { finished in print("Basket doors opened!") }
// Combining with modifiers
Button()
.action: {
// ...
}
.label: {
//...
}
.padding(20)
Button.action: {
// ...
}.label: {
//...
}.padding(20)
// A call builder metafunction called `.:` to allow unambiguous unlabeled last argument
array.contains.: { $0 == 1 }