Background
SE-0279, which is currently in second review, includes the following:
It is in the proposal as part of the explanation for the label handling with multiple trailing closures, but the guidance applies just as much to existing trailing closures. Using argument labels for "trailable" closures is at best semi-pointless and sometimes actively harmful. This becomes clear when you look at some standard library examples:
// this reads well
array.first(where: { criteria })
// but this is not at all clear
array.first { criteria }
// this reads... eh, ok, still a little ambiguous
array.drop(while: { criteria })
// but is this filtering all of them out? dropping after first match?
array.drop { criteria }
The simple solution of applying the beneficial argument label to the base name instead would make these considerably more readable regardless of whether the trailing closure is applied:
array.firstWhere({ criteria })
array.firstWhere { criteria }
array.dropWhile({ criteria })
array.dropWhile { criteria }
With trailing closures as they stand, it turns out it is never a good idea to make your trailing closure label meaningful because it will be left off 90% of the time, and having a label that appears only when parentheses happen to wrap the closure isn't a good practice.
Additionally, we have the case of SE-0220 which introduced Sequence.count(where: (Element)->Bool)
, which had to be backed out because the basename was ambiguous with Collection.count
, leading to performance problems in the type checker:
// SE-0220 caused expressions like these to take longer to type check
queue.count + (task?.queue.count ?? 0)
In this example, the typechecker must consider whether queue.count
was referring to Collection.count
or the function ((Int) -> Bool) -> Int
. Eventually it can figure it out based on the integer literal, but this massively expanded the search space to explore, lengthening compile times. Re-introducing count(where:)
as countWhere(_:)
would both improve readability at the call site and sidestep the typechecker issue.
Proposal
A review of the standard library should be undertaken on all high-order functions to determine whether their argument label is important, and if so, recommend adding a second method with the argument label hoisted into the basename. This would be source breaking, but justified under the "active harm" exception, since the readability of methods such as drop(while:)
is currently severely impaired by dropping the argument label. The original method should be deprecated over time (probably when we next introduce a new language variant).
Note, not all argument labels are necessary for readability, and would have been better left out altogether. These should be left alone rather than changed for consistency, since the bar for source breakage is high.