-1
Debatable. Making call sites to functions with many parameters readable is challenging, and this is compounded for closure parameters (which may encourage multi-line arguments at the call site). Clearly the single-closure case was significant enough to merit special syntax, so this seems to be expanding to another (smaller) special case.
This is where this proposal falls down in my estimation, for two reasons. First, it is inconsistent with the precedent of single trailing closure syntax. Second, it is inconsistent with the established precedent for what curly braces signify in Swift.
As others have noted, the special-case syntax for a single trailing closure both reduced the nesting level of delimiters in an expression and mimics the syntax of many built-in statements. The new proposed syntax has neither of those benefits, and doesn’t actually extend the existing trailing closure syntax (it isn’t like the old syntax is an instance of the new syntax).
One of the main departures of Swift syntax from C precedent is greater consistency in how delimiters are used:
-
()
is used around heterogeneous, comma-separated sequences, where both order/count of terms and labels matter (used both for parameter and argument lists) -
[]
is used around homogeneous, comma-separated sequences, where order may matter, but the number of terms is not relevant to the type. (It is also used when invoking subscripts: a minor internal inconsistency in order to follow C precedent, which at least cements[]
as having to do with collections) -
{}
is used around bodies that either consist of unordered declarations, or an ordered mix of declarations and statements.
This proposal adds a new special-case meaning to {}
that overlaps more (but imperfectly) with the existing role of ()
than it does with existing usage of {}
.
(Note that function builders layer new semantics on top of a subset of the existing {}
syntax, rather than being something entirely new.)
This would be the first case of {}
being used to contain something other than declarations or statements, and the first case where it is used with key: value
terms.
My sense is that this feature might make sense if it was either pitched as something that can apply to all argument lists aimed at making thing more pleasant when calling functions with many parameters (e.g., keeping ()
and focusing on eliminating commas), or if it figured out a way to make this feature actually be an extension of existing trailing closure syntax and its goals (i.e., reduce nesting depth and enable syntax like that of built-in statements).
While not closely related semantically, the chosen syntax ends up overlapping with instance creation (new
) expressions in Java, Scala, and C#.
In C#, new
expressions allow a mix of positional arguments inside ()
(which map for constructor parameters) and key = value
initialization inside {}
(which map to property assignments performed after construction). This style is typically used for classes that have many properties such that a constructor that supported them all would be unwieldy. There is no rule related to the types of properties (e.g., only allowing closures in one of the argument lists), as the {}
part is a general-purpose feature loosely based on C99 designated initializers.
Scala (and also Java, IIRC) allow for both new
expressions that use ()
for constructor arguments, and ones that use {}
to declare an anonymous subclass at the use site (I don’t recall if mixing the two is ever allowed). In this case the {}
-delimited body is just like any other class body.
The flexibility of Scala class bodies (which can contain both declarations and statements that become the body of the primary constructor for a class) means that its syntax can in principle support both single-trailing-closure cases and the moral equivalent of this proposal with the same feature.
In all of these precedents I’m aware of for mixing ()
and {}
the feature is general-purpose and builds on existing uses for {}
-delimited blocks in the language.
I’ve followed the pitch thread and did a bit of study to refresh my memory of how similar syntax in other languages works.