Search code examples
swiftparameter-pack

How does a Swift parameter pack solve the stated motivational problem?


The Swift evolution parameter packs proposal begins with a Motivation section that cites the following bit of familar ugliness:

func < (lhs: (), rhs: ()) -> Bool

func < <A, B>(lhs: (A, B), rhs: (A, B)) -> Bool where A: Comparable, B: Comparable

func < <A, B, C>(lhs: (A, B, C), rhs: (A, B, C)) -> Bool where A: Comparable, B: Comparable, C: Comparable

The problem here is that in order to implement comparison of tuples, we have to implement it for 2-tuples, implement it again for 3-tuples, and so on. And furthermore this repetition means that we have to give up after some arbitrary maximum tuple size (6-tuples).

My question is: exactly how do Swift parameter packs solve this problem? Looking in the headers for Swift 6, I do not see that the declaration of tuple < has changed from earlier Swift versions. (Indeed, I don't see any use of parameter packs in the Swift headers, period.) And in any case (and more to the point), parameter packs are not about tuples at all; they are about variadics.

So I can see instantly how we would implement comparison between two variadic lists of Comparable values:

func isLessThan<each T: Comparable>(lhs: repeat each T, rhs: repeat each T) -> Bool {
    for pair in repeat (each lhs, each rhs) {
        if pair.0 >= pair.1 {
            return false
        }
    }
    return true
}

And we can call it like this:

let result = isLessThan(lhs: 1, "a", rhs: 2, "b")

Great — but those are not tuples. They are variadic lists. The root of the issue is that there is no way to make a variadic list dynamically: you can't turn a tuple (or a sequence) into a variadic list.

So how do parameter packs solve the motivational problem?


Solution

  • You can write the function signature like this to make it work with tuples:

    func isLessThan<each T: Comparable>(lhs: (repeat each T), rhs: (repeat each T)) -> Bool
    

    I'd like to think of a pack expansion like repeat each T as T1, T2, T3, ..., Tn. Then naturally, (repeat each T) is a tuple, (T1, T2, T3, ..., Tn).

    The body of the function can remain unchanged.


    Side note, it is planned that tuples will be Comparable.