Artem Stepanenko Artem Stepanenko - 1 month ago 20
iOS Question

Closures shorthand syntax in Swift 3

What's the difference from the compiler's perspective between expressions 1 and 2 (see the screenshot below)? If since Swift 3 it's not possible anymore to pass multiple params to functions in a form of a tuple, then how comes the first expression still works?

func f(_ x: Int, _ y: Int) -> Int {
return x + y
}

// compiles
[(1, 2)].map(f)

// doesn't compile: "Passing 2 arguments to a callee as a single tuple value has been removed in Swift 3"
[(1, 2)].map { (t: (Int, Int)) -> Int in
return f(t)
}

Answer

The rationale is explained in the proposal that removed it. It created subtle problems in the second case, but not in the first. And, as in the case of most "why does the compiler not throw an error here," the answer is "because it doesn't prevent it." It doesn't always mean there was a deep intention at work. Sometimes it works because it wasn't prevented from working.

But, it's also true that this isn't actually a special case in the first example. This works, too, with labels:

func f(x: Int, y: Int) -> Int { ... }
[(1, 2)].map(f)

In the second example, that didn't used to work because it runs up against the fact that tuple labels are not part of the type, so there isn't currently a way to express it correctly (this being one of the subtle problems). See:

It is important to note that this is a feature common in functional languages, but Swift is not a functional language, doesn't intend to be one, and has removed several existing functional features in Swift 3 to make the language more coherent (most famously, curry syntax, which also really fought against how Swift intends to works). The way you've defined f() is extremely un-Swift-like, both being a top-level function (which Swift avoids) and by not naming its parameters. Swift allows such things, but doesn't cater to them. The Swift team is anxious to hear examples where this syntax would be useful, and that map to common problems that Swift developers are likely to encounter (they've indicated they would explore re-adding the feature more fully if such examples were presented). See the evo-proposal for the thread to discuss this on if you have examples.

Broadly, tuples in Swift are weak sauce. They don't live up to being real "anonymous structs" the way you would expect, and are barely first-class types (you can't attach extensions to them, for instance). There are several proposals open to improve tuples, but in Swift 3, they aren't really a very powerful tool beyond very simple uses.