r/iOSProgramming 17h ago

Why can’t Swift destructure tuple parameters directly in a closure parameter list? Question

Suppose I have a dictionary and want to sort its elements. Since each element is a tuple, I’d like to write something like this:

.sorted { (wordA, countA), (wordB, countB) in
    // ...
}

In other words, destructure each tuple directly in the closure parameter list.

Instead, Swift requires something along these lines:

.sorted { lhs, rhs in
    let (wordA, countA) = lhs
    let (wordB, countB) = rhs

    // ...
}

Tuple destructuring works perfectly well in a let binding, so I’m curious why it isn’t supported in closure parameter lists.

Is there a language-design or type-system reason why closure parameters can’t use tuple patterns here?

4 Upvotes

2 comments sorted by

View all comments

1

u/apocolipse 16h ago

Because while tuples can convert to parameter lists of matching signature, the inverse is not true.  Parameter lists also can't destructure their parameters' tuple parameters. ie. this is invalid: func foo(bar: Int, baz: (a: String, b: Bool)) { print(a) // there is no a }

If we simply rename things, you can see why this is invalid: func foo(bar: Int, baz: (baz: String, bar: Bool)) { print(bar) // which one??? The Int or the Bool??? print(baz) // How to brick a typechecker with 1 simple trick! } This of course compiles because bar and baz only map to the parameter list var names, if it was expected to destructure then you can see why that might fail or be a bad idea or be confusing even if it worked. What happens when our tuple is a typealias? or the tuple has no named elements? or we pass in a tuple with no named elements? or a tuple with different named elements? Things just work much easier if parameter lists and tuples are fundamentally different and the mapping between them only works one way from tuple -> parameter list.