Skip to content

Commit 1054c86

Browse files
committed
Replace the value expansion operator with a member to access tuple
elements as a pack. This eliminates one of the added meanings of '...' and is more generally useful than tuple splat.
1 parent 77284ce commit 1054c86

File tree

1 file changed

+9
-17
lines changed

1 file changed

+9
-17
lines changed

vision-documents/variadic-generics.md

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -281,39 +281,32 @@ func iterate(over tuple: Tuple<Int, String, Bool>) {
281281
}
282282
```
283283

284-
### Value expansion operator (aka "tuple splat")
284+
### Accessing tuple elements as a pack
285285

286-
To achieve the goal of using variadic generics to generalize structural types, this design includes the ability to expand tuple values into a list of individual element types, unlocking all the same expressivity for tuples without introducing an additional set of operations for mapping, iteration, concatenation, and de-structuring.
286+
To achieve the goal of using variadic generics to generalize tuple types, this design includes the ability to access the elements of a tuple value as a value pack, unlocking all the same expressivity for tuples without introducing an additional set of operations for mapping, iteration, concatenation, and de-structuring.
287287

288-
An abstract tuple value contains a list of zero or more individual values. The *value expansion operator*, spelled with `...`, removes the tuple structure, leaving a comma-separated list of zero or more individual values that can be used anywhere that accepts a value pack expansion:
288+
An abstract tuple value contains a list of zero or more individual values. Packing the elements of a tuple removes the tuple structure, and collects the individual tuple elements into a value pack. This operation is a special property on tuple types called `.element`:
289289

290290
```swift
291291
struct Mapped<Value> {}
292292

293293
func map<T...>(tuple: (T...)) -> (Mapped<T>...) {
294-
let element = tuple... // expands 'tuple' into a local variable pack
295-
return (Mapped(element)...)
294+
return (Mapped(tuple.element)...)
296295
}
297296
```
298297

299-
Similar to concrete value packs, using the value expansion operator on concrete or partially concrete tuples requires a type annotation for the abstract element type:
298+
The `element` property returns the elements of a tuple in a single pack. For an abstract tuple `(T...)`, the signature of this property is `(T...) -> T`, which is otherwise not expressible in the language. For a tuple of length *n*, the complexity of converting a tuple value to a pack is *O(n)*.
299+
300+
Similar to concrete value packs, using the pack operation on concrete or partially concrete tuples requires a type annotation for the abstract element type:
300301

301302
```swift
302303
func iterate(over tuple: (Int, String, Bool)) {
303-
for value: some Equatable in tuple... {
304+
for value: some Equatable in tuple.element... {
304305
// do something with an 'Equatable' value
305306
}
306307
}
307308
```
308309

309-
To express individual tuple elements in repetition patterns, e.g. to expand the elements of a tuple in parallel with a pack or another tuple, the tuple must first be expanded into a local variable pack. This may become a common pattern in variadic generic code, and it may be useful to add an explicit operator to turn a tuple value into a pack directly in the pattern of a pack expansion. For illustrative purposes, a possible syntax for converting a tuple to a pack without an intermediate local variable is `tuple as T` where `T` is a reference to a type pack:
310-
311-
```swift
312-
func map<T...>(tuple: (T...)) -> (T?...) {
313-
return ((tuple as T)?...)
314-
}
315-
```
316-
317310
### User-defined tuple conformances
318311

319312
The above features together provide the necessary tools for writing abstractions over tuples with variable length. The last major expressivity gap between tuples and nominal types is the ability to declare conformances on tuples. This design finally closes that gap, using a parameterized extension syntax to declare the conformance:
@@ -384,13 +377,12 @@ Packs can also be used in the parameter list of a function type; if packs were t
384377

385378
## Exploring syntax alternatives
386379

387-
This design for variadic generics results introduces 3 new meanings of `...`, leaving Swift with 5 total meanings of `...`:
380+
This design for variadic generics results introduces 2 new meanings of `...`, leaving Swift with 4 total meanings of `...`:
388381

389382
1. Non-pack variadic parameters
390383
2. Postfix partial range operator
391384
3. Type parameter pack declaration
392385
4. Pack expansion operator
393-
5. Value expansion operator
394386

395387
Choosing an alternative syntax may alleviate ambiguities with existing meanings of ... in Swift. The authors of this vision document are open to considering an alternative syntax, but have yet to find a more compelling one.
396388

0 commit comments

Comments
 (0)