Pitching The Start of Variadic Generics

I really want to see variadic generics in the Swift, so I'm very happy to see this pitch.


Composition of type sequences would be hard with this pitch. For example, I can imagine a type witch takes variadic (T) -> U arguments. But maybe it is difficult:

// desired behavior
foo(closures: { (a: Int) in a + 1 }, { (a: String) in print(a) }, { (a: Bool) in a ? "true" : "false" })

// maybe error, since the length of T... and U... is not always equal
func foo<T..., U...>(closures: ((T) -> U)...) {}

// however, since there is no relation ship between T... and U..., constraint like `T == Set<U>` cannot be added

It's just an idea, but maybe some (T, U)... type sequences can solve this problem.

// maybe error, since the length of T... and U... is not always equal
func foo<(T, U)...>(closures: ((T) -> U)...) {}

With it, allPresent example changes like this:

// it ensures that T... and U... have the same length
func allPresent<(T, U)...>(haystacks: T..., needles: U...) -> Bool
  where T == Set<U>  // such constraint can only be added to (T, U)... type sequence
{ /* ... */ }

Does T... allows zero-length type sequence? Considering current variadics allows zero length parameters, it is natural to allow them.

func foo<T...>(_ value: T...) {}
foo()

However, I think then it is difficult to express some constraints. Consider creating HomogeneousTuple struct.

struct HomogeneousTuple<T...> {}

Of course this is not correct, since T... allows heterogeneous types. Therefore, you have to write like this:

@dynamicMemberLookup
struct HomogeneousTuple<Element, T...> where T = Element {
    var tuple: (T...)
    subscript<U>(dynamicMember keyPath: WritableKeyPath<(T...), U> -> U {
        get { tuple[keyPath: keyPath] }
        set { tuple[keyPath: keyPath] = newValue }
    }
}

However, on the use-site, it becomes strange type:

let hTuple: HomogeneousTuple<Int, Int, Int> // this is two-length HomogeneousTuple actually!!

Maybe some solution must be prepared for it. I thought generic where I described here can be one solution, but there will be neat way.


Some thought:

  • Is there any possibility to consider variadic - reverse generics? Returning opaque length of type sequence would be intresting.

  • I don't think the strategy to have _countTypeSequence, _mapTypeSequence, and other build-in operations is enough. Maybe it turns endless addition of reserved name for zip, reversed, rotated, and so on? But I don't have any idea to enable such operation without built-in :cry:

    • In the allPresent example, zip(haystacks, needles) naturally appears, and I'm confused. Do type sequences conform Sequence?