# Variadic Generics

**URL:** <https://forums.swift.org/t/variadic-generics/54511>\
**Category:** Pitches\
**Tags:** generics\
**Created:** [January 8, 2022, 5:38am UTC](https://forums.swift.org/t/variadic-generics/54511 "2022-01-08T05:38:55Z")\
**Posts on this page:** 1\
**Showing post:** 8

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [January 8, 2022, 6:02pm UTC](https://forums.swift.org/t/variadic-generics/54511/8 "2022-01-08T18:02:55Z")

</div>

Thanks for your continued work on this, @codafi!

I remain somewhat averse to the `...` spelling for reasons mentioned in the previous thread. Most concerning to me is:

> [@Pitching The Start of Variadic Generics](https://forums.swift.org/t/pitching-the-start-of-variadic-generics/51467/5):
>
> The bigger issue for me when it comes to the `...` spelling is how it pans out for generic types. From the body of the example `ZipSequence` type:
> 
> ```swift
> public init(_ seqs: Sequences...) {
> self.seqs = seqs  
> }
> 
> ```
> 
> The only way we can tell for sure that `Sequences` is a variadic type sequence rather than `seqs` being a variadic parameter is to inspect the generic signature where `Sequences` is declared. While this is not so much of an issue for functions (since the generic parameter will always be fairly local to its use), type members may be defined in a separate extension, which means they could be in a disparate part of the file, another file, or another module entirely.

IMO, although the `...` syntax is nice and terse, the potential breakdown of local reasoning ability is a good reason to prefer something else.

* * *

I don't know where exactly the Swift API design guidelines sit with regard to Swift evolution, but I think that as part of the variadic generics design we should settle on some conventions which could eventually be subsumed as part of the API guidelines. In particular, I am still bothered by the interchangeable use of plural and singular terminology for generic parameter packs. It looks like this proposal has _mostly_ settled on plural terminology (though we still have some `T`, `U` usages rather than `Ts` and `Us`), but IMO that becomes a bit problematic given:

> [@codafi](#):
>
> The type parameter `Ts` is the “pattern type” of the constituent elements of the pack.

because it means that the parameter name is used in contexts that refer to the aggregate pack (plural) as well as the _individual constituent pack types_. I think this makes for some confusing signatures such as:

> [@codafi](#):
>
> ```swift
> public struct ZipSequence<Sequences...>: Sequence
> where Sequences: Sequence 
> {
> 
> ```

Here, `Sequences: Sequence` is really saying "each constituent type of `Sequences` is itself a `Sequence`, but IMO a perfectly plausible reading of this is "the `Sequences` pack is a `Sequence` itself." This particular example is made even more confusing by the fact that the erroneous interpretation is in fact _true_, since the pack as a whole _does_ conform to `Sequence`.

This strangeness can also be seen in:

> [@codafi](#):
>
> ```swift
> func printTypes<Args...>(_ items: Args...) {
> for (item: Args) in items {
> print(type(of: item), item)
> }
> }
> 
> ```

The type of `item` is really a _single_ 'arg' from the `Args...` pack, but the use of the plural terminology reads as if `item` is itself some sort of aggregate type.

I'd really like it if we could have a design which allows for explicit differentiation between the singular usage and the aggregate usage of the variadic parameter names. In the previous pitch I came up with a somewhat verbose `forEach` syntax that would allow for the explicit introduction of the 'singular' name of a variadic parameter:

> [@Pitching The Start of Variadic Generics](https://forums.swift.org/t/pitching-the-start-of-variadic-generics/51467/5):
>
> ```swift
> func allPresent<Haystacks..., Needles...>(haystacks: Haystacks..., needles: Elements...) -> Bool
> where forEach(Haystack in Haystacks, Needle in Needles, Haystack == Set<Needle>)
> 
> ```

but I'd also be fine with some sort of syntax that indicates "we're really talking about an _arbitrary element_ of this pack, maybe something like:

```swift
public struct ZipSequence<Sequences...>: Sequence
  where Sequences[_]: Sequence 
{

```

ETA: @QuinceyMorris's suggestion of always preferring the _singular_ spelling for variadic generic parameters is also compelling to me, and wouldn't require the invention of new syntax to refer to a singular element. The bare name (e.g., `Arg`) would always refer to a singular element, and the aggregate would always be spelled with the trailing `...` (e.g., `Arg...`). That also agrees with the existing usage of `...` for variadic parameters, for which we write the _singular_ type name and use `...` to 'pluralize' it, e.g., `Int...`.

Regardless of which direction we choose, though, I think the proposal should take an opinionated stance on the 'right' way to design variadic generic signatures.

* * *

I'm also still wondering if we really need to introduce the new "generic parameter packs" to the language:

> [@Pitching The Start of Variadic Generics](https://forums.swift.org/t/pitching-the-start-of-variadic-generics/51467/22):
>
> Another thing I've been mulling over is whether we need to have a bright-line distinction between "type sequences" and "tuples". That is, if we add all the special operators ( `_countTypeSequence` , `_mapTypeSequence` , etc.), would it be sufficient to say that a generic parameter `T*` declares a type `T` which stands for a tuple of arbitrary arity? Then, we could have a tuple-splat operator for turning a `T` value into its constituent parts (for e.g. function application). This might also dovetail nicely with [`@expanded`](https://forums.swift.org/t/gsoc-shared-storage-for-property-wrappers-and-expanded-parameters/51355) to give us a way of expanding a variadic tuple into a parameter list, e.g.:
> 
> ```swift
> func variadic<Tuple*>(args: @expanded Tuple)
> // or
> func variadic<Tuple*>(args: #splat(Tuple))
> // or, maybe 'Tuple' means the tuple version of the 
> // type, and 'Tuple*' the splatted version
> func variadic<Tuple*>(args: Tuple*)
> 
> ```
> 
> all of these could indicate that `variadic` is callable as:
> 
> ```swift
> variadic("Hello", 1, 2.0)
> 
> ```
> 
> This could also imply (though it wouldn't _have_ to) that all the special type sequence operations would be applicable to fixed-size tuples as well:
> 
> ```swift
> for elt in ("Hello", 1, 2.0) {
> // elt is 'Any' here?
> }
> 
> ```

If we were to 'superpower' tuples, could we get away with not introducing an entirely new concept to the language? Is there a fundamental expressivity issue with tuples that prevents us from realizing everything we would want from variadic parameters?

* * *

Regarding the "only one variadic parameter in a generic type" rule, is this a restriction we want to lift eventually? If so, could we allow such types to be defined and rely on generic parameter inference to fill in each pack appropriately?

> [@Pitching The Start of Variadic Generics](https://forums.swift.org/t/pitching-the-start-of-variadic-generics/51467/36):
>
> However, we allow generic parameters to be inferred in many (most?) cases, so if multiple variadic parameters are allowed in `Zip` 's `init` it seems reasonable that we could write:
> 
> ```swift
> let z = Zip(xs: a, b, ys: c, d, e)
> 
> ```
> 
> And have the generic parameters to `Zip` inferred. Then we could worry about the syntax for explicit parameterization later.

---

_[View the full topic](https://forums.swift.org/t/variadic-generics/54511)._
