I've added a note about naming convention to the document. I'll paste it here for ease of quoting for further questions, thoughts, and other feedback. Please let me know what you think!
A note on naming convention
In code, programmers naturally use plural names for variables representing lists. However, in this design for variadic generics, pack names can only appear in repetition patterns where the type or expression represents an individual type or value that is repeated under expansion. The recommended naming convention is to use singular names for parameter packs, and plural names only in argument labels:
struct List<Element...> {
let element: Element...
init(elements element: Element...)
}
List(elements: 1, "hello", true)
More broadly, packs are fundamentally different from first-class types and values in Swift. Packs themselves are not types or values; they are a special kind of entity that allow you to write one piece of code that is repeated for N individual types or values. For example, consider the element
stored property pack in the List
type:
struct List<Element...> {
let element: Element...
}
The way to think about the property pack let element: Element...
is "a property called element
with type Element
, repeated N times". When List
is initialized with 3 concrete arguments, e.g. List<Int, String, Bool>
, the stored property pack expands into 3 respective stored properties of type Int
, String
, and Bool
. You might conceptualize List
specialization for {Int, String, Bool}
like this:
struct List<Int, String, Bool> {
let element.0: Int
let element.1: String
let element.2: Bool
}
The singular nature of pack names becomes more evident with more sophisticated repetition patterns. Consider the following withOptionalElements
method, which returns a new list containing optional elements:
extension List {
func withOptionalElements() -> List<Optional<Element>...> {
return List(elements: Optional(element)...)
}
}
In the return type, the repetition pattern Optional<Element>...
means there is an optional type for each individual element in the parameter pack. When this method is called on List<Int, String, Bool>
, the pattern is repeated once for each individual type in the list, replacing the reference to Element
with that individual type, resulting in Optional<Int>, Optional<String>, Optional<Bool>
.
The singular naming convention encourages this model of thinking about parameter packs.