You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -92,9 +92,11 @@ Parameter packs are the core concept that facilitates abstracting over a variabl
92
92
funczip<eachS: Sequence>(...)
93
93
```
94
94
95
-
A parameter pack itself is not a first-class value or type, but the elements of a parameter pack can be used anywhere that naturally accepts a comma-separated list of values or types using _pack expansions_. A pack expansion unpacks the elements of a pack into a comma-separated list, and elements can be appended to either side of a pack expansion by writing more values in the comma-separated list.
95
+
A parameter pack itself is not a first-class value or type, but the elements of a parameter pack can be used anywhere that naturally accepts a list of values or types using _pack expansions_, including top-level expressions.
96
96
97
-
A pack expansion consists of the `repeat` keyword followed by a type or an expression. The type or expression that `repeat` is applied to is called the _repetition pattern_. The repetition pattern must contain pack references. Similarly, pack references can only appear inside repetition patterns and generic requirements:
97
+
A pack expansion consists of the `repeat` keyword followed by a type or an expression. The type or expression that `repeat` is applied to is called the _repetition pattern_. The repetition pattern must contain at least one pack reference, spelled with the `each` keyword. At runtime, the pattern is repeated for each element in the substituted pack, and the resulting types or values are _expanded_ into the list provided by the surrounding context.
98
+
99
+
Similarly, pack references can only appear inside repetition patterns and generic requirements:
@@ -105,12 +107,11 @@ Given a concrete pack substitution, the pattern is repeated for each element in
105
107
Here are the key concepts introduced by this proposal:
106
108
107
109
- Under the new model, all existing types and values in the language become _scalar types_ and _scalar values_.
108
-
- A _type pack_ is a new kind of type which represents a list of scalar types. Type packs do not have syntax in the surface language, but we will write them as `{T1, ..., Tn}` where each `Ti` is a scalar type. Type packs cannot be nested; type substitution is defined to always flatten type packs.
109
-
- A _type parameter pack_ is a type parameter which can abstract over a type pack. These are declared in a generic parameter list using the syntax `each T`, and referenced with `each T`.
110
-
- A _pack expansion type_ is a new kind of scalar type which flattens a set of type packs in a context where a comma-separated list of types may appear. The syntax for a pack expansion type is `repeat each P`, where `P` is a type containing one or more type parameter packs.
110
+
- A _type pack_ is a new kind of type-level entity which represents a list of scalar types. Type packs do not have syntax in the surface language, but we will write them as `{T1, ..., Tn}` where each `Ti` is a scalar type. Type packs cannot be nested; type substitution is defined to always flatten type packs.
111
+
- A _type parameter pack_ is a list of zero or more scalar type parameters. These are declared in a generic parameter list using the syntax `each T`, and referenced with `each T`.
111
112
- A _value pack_ is a list of scalar values. The type of a value pack is a type pack, where each element of the type pack is the scalar type of the corresponding scalar value. Value packs do not have syntax in the surface language, but we will write them as `{x1, ..., xn}` where each `xi` is a scalar value. Value packs cannot be nested; evaluation is always defined to flatten value packs.
112
-
- A _value parameter pack_ is a function parameter or local variable declared with a pack expansion type.
113
-
- A _pack expansion expression_is a new kind of expression whose type is a pack expansion type. Written as `repeat each expr`, where `expr` is an expression referencing one or more value parameter packs.
113
+
- A _value parameter pack_ is a list of zero or more scalar function or macro parameters.
114
+
- A _pack expansion_is a new kind of type-level and value-level construct that expands a type or value pack into a list of types or values, respectively. Written as `repeat P`, where `P` is the _repetition pattern_ that captures at least one type parameter pack (spelled with the `each` keyword). At runtime, the pattern is repeated for each element in the substituted pack.
114
115
115
116
The following example demonstrates these concepts together:
116
117
@@ -168,7 +169,7 @@ A pack expansion type, written as `repeat P`, has a *pattern type* `P` and a non
168
169
* The type of a parameter in a function type, e.g. `(repeat each T) -> Bool`
169
170
* The type of an unlabeled element in a tuple type, e.g. `(repeat each T)`
170
171
171
-
Because pack expansions can only appear in positions that accept a comma-separated list, pack expansion patterns are naturally delimited by either a commaor the end-of-list delimiter, e.g. `)` for call argument lists or `>` for generic argument lists.
172
+
Because pack expansions can only appear in positions that accept a list of types or values, pack expansion patterns are naturally delimited by a comma, the next statement in top-level code, or an end-of-list delimiter, e.g. `)` for call argument lists or `>` for generic argument lists.
172
173
173
174
The restriction where only unlabeled elements of a tuple type may have a pack expansion type is motivated by ergonomics. If you could write `(t: repeat each T)`, then after a substitution `T := {Int, String}`, the substituted type would be `(t: Int, String)`. This would be strange, because projecting the member `t` would only produce the first element. When an unlabeled element has a pack expansion type, like `(repeat each T)`, then after the above substitution you would get `(Int, String)`. You can still write `0` to project the first element, but this is less surprising to the Swift programmer.
174
175
@@ -466,20 +467,20 @@ The type annotation of `tup` contains a pack expansion type `repeat (each T, eac
466
467
467
468
#### Restrictions on same-shape requirements
468
469
469
-
While type packs cannot be written directly, a requirement where both sides are concrete types is desugared using the type matching algorithm, therefore it will be possible to write down a requirement that constrains a type parameter pack to a concrete type pack, unless some kind of restriction is imposed:
470
+
Type packs cannot be written directly, but requirements involving pack expansions where both sides are concrete types are desugared using the type matching algorithm. This means it is possible to write down a requirement that constrains a type parameter pack to a concrete type pack, unless some kind of restriction is imposed:
Furthermore, since the same-type requirement implies a same-shape requirement, we've implicitly constrained `T` to having a length of 2 elements, without knowing what those elements are.
476
+
Furthermore, since the same-type requirement implies a same-shape requirement, we've implicitly constrained `S` to having a length of 2 elements, without knowing what those elements are.
476
477
477
478
This introduces theoretical complications. In the general case, same-type requirements on type parameter packs allows encoding arbitrary systems of integer linear equations:
478
479
479
480
```swift
480
481
// shape(Q) = 2 * shape(R) + 1
481
482
// shape(Q) = shape(S) + 2
482
-
funcsolve<eachQ, eachR, eachS>(q: repeateach Q, r: repeateach R, s: repeateachS)
@@ -500,7 +501,7 @@ This aspect of the language can evolve in a forward-compatible manner. Over time
500
501
501
502
### Value parameter packs
502
503
503
-
A _value parameter pack_ represents zero or more function arguments, and it is declared with a function parameter that has a pack expansion type. In the following declaration, the function parameter `value` is a value parameter pack that receives a _value pack_ consisting of zero or more argument values from the call site:
504
+
A _value parameter pack_ represents zero or more function or macro parameters, and it is declared with a function parameter that has a pack expansion type. In the following declaration, the function parameter `value` is a value parameter pack that receives a _value pack_ consisting of zero or more argument values from the call site:
@@ -510,7 +511,7 @@ _ = tuplify(1) // T := {Int}, value := {1}
510
511
_=tuplify(1, "hello", [Foo()]) // T := {Int, String, [Foo]}, value := {1, "hello", [Foo()]}
511
512
```
512
513
513
-
**Syntactic validity:** A value parameter pack can only be referenced from a pack expansion expression. A pack expansion expression is written as `repeat expr`, where `expr` is an expression containing one or more value parameter packs or type parameter packs spelled with the `each` keyword. Pack expansion expressions can appear in any position that naturally accepts a comma-separated list of expressions. This includes the following:
514
+
**Syntactic validity:** A value parameter pack can only be referenced from a pack expansion expression. A pack expansion expression is written as `repeat expr`, where `expr` is an expression containing one or more value parameter packs or type parameter packs spelled with the `each` keyword. Pack expansion expressions can appear in any position that naturally accepts a list of expressions, including comma-separated lists and top-level expressions. This includes the following:
514
515
515
516
* Call arguments, e.g. `generic(repeat each value)`
516
517
* Subscript arguments, e.g. `subscriptable[repeat each index]`
@@ -519,8 +520,6 @@ _ = tuplify(1, "hello", [Foo()]) // T := {Int, String, [Foo]}, value := {1, "hel
519
520
520
521
Pack expansion expressions can also appear in an expression statement at the top level of a brace statement. In this case, the semantics are the same as scalar expression statements; the expression is evaluated for its side effect and the results discarded.
521
522
522
-
Note that pack expansion expressions can also reference _type_ pack parameters, as metatypes.
523
-
524
523
**Capture:** A pack expansion expression _captures_ a value (or type) pack parameter the value (or type) pack parameter appears as a sub-expression without any intervening pack expansion expression.
525
524
526
525
Furthermore, a pack expansion expression also captures all type parameter packs captured by the types of its captured value parameter packs.
Thank you to Robert Widmann for exploring the design space of modeling packs as tuples, and to everyone who participated in earlier design discussions about variadic generics in Swift.
836
+
Thank you to Robert Widmann for exploring the design space of modeling packs as tuples, and to everyone who participated in earlier design discussions about variadic generics in Swift. Thank you to the many engineers who contributed to the implementation, including Sophia Poirier, Pavel Yaskevich, Nate Chandler, Hamish Knight, and Adrian Prantl.
0 commit comments