You are contemplating SE-0111. This will help you perform searches in the forum archive.
Users frequently complain about the inability to name closure arguments (i.e. it is impossible to write f(a: 3) if f is defined as a closure). User complain because this breaks the object/closure symmetry, and makes the language irregular.
Objects (data with behaviors) and closures (behaviors that close over data) are supposedly roughly equivalent, which means that one should be able to freely choose between those two forms, for whatever reason deemed relevant:
// Form 1: sure, why not
protocol P { func f(_ x: Int) }
let object: P = ...
object.f(1)
// Form 2: sure, looks good as well
let closure: (Int) -> Void = ...
closure(1)
Unfortunately, this freedom is hindered by SE-0111 as soon as one wants to use argument labels. Only regular methods can have them, and closures are out of the game.
This creates developer frustration, because a developer often discovers too late that the closure path is hindered by SE-0111. After one has successfully toyed with closures that do not need argument labels, enjoyed the game, and started relying on closures, one suddenly hits a wall.
This explains why users frequently ask that argument labels in closures come back.
Now, asking is far from enough for the language to be changed (see the Swift Evolution Process), so nothing happens.
I, uh, object to this characterization. It’s frustrating that closures don’t get the benefits of argument labels, but closures and objects aren’t anywhere close to interchangeable anyway in Swift: objects have methods and closures do not. Even the original asker was comparing functions and closures.
In any case, it may help understanding to observe the following additional behavior:
var g = f
g(3) // not g(a: 3)
g = c
g(3) // still not g(a: 3)
Argument labels are part of a function’s name. Closures don’t have names; the lets and vars and parameters you put them in do. So if someone were to add argument labels for closures (which I support), it would be sugar for something like this:
let `c(a:)` = { … }
c(a: 3)
var `g(x:)` = f
g(x: 3)
g = c
g(x: 3)
Wait, would you really need the backticks there? I've spent this whole time imagining that the final syntax for closures with argument labels would be:
I deliberately picked a very explicit syntax to make it clear what was going on; other syntaxes may be possible as well. The most important place for this is parameters anyway, and there I think we’d want to support interleaving the labels with the type, whether or not that was supported anywhere else.
I'd definitely enjoy being able to use argument labels with closures.
@tera, regarding your suggestion, would this be allowed?
let concat <T>([T]) -> (to: [T]) -> [T] =
{ x in
{ y in y + x }}
concat ([3, 4]) (to: [1,2])
I'd love to be able to do this very much! I personally have a tough time with deciphering function signatures when types are mixed into the signature. I also like being able to reason about types separately. Currently, it's not really feasible to avoid this in apps beyond simple toy apps.
The only thing this doesn't quite address is making function types more portable, right now in Swift, we can't reuse function types with the standard way of defining named functions. The below functions have the same type signature but there's not a way to share them with each other. And there's not really a way to do this when assigning closures to variables because we can't specify generics when calling that kind of function:
typealias myType<T> = ((T) -> Bool, [T]) -> [T]
let filter:myType = { fn, someArray in someArray.filter(fn) }
let reject:myType = { fn, someArray in someArray.filter { item in !fn(item) } }
// or if labels in the typealias is desired
typealias myType<T> = (_ fn: (T) -> Bool, to someArray: [T]) -> [T]
let filter:myType = { someArray.filter(fn) }
let reject:myType = { someArray.filter { item in !fn(item) } }
I think the ideas are complementary and would really help out developers like myself that find it hard to parse a function signature when everything is all mixed together. I'd be extremely happy with and helped out by either/or though!