Variadic Generics

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:

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:

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:

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:

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:

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:

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:

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?

11 Likes