Skip to content

Commit 8b472d8

Browse files
committed
Add better example code to demonstrate the difference between tuples and packs.
1 parent 4d4fb5f commit 8b472d8

File tree

1 file changed

+43
-3
lines changed

1 file changed

+43
-3
lines changed

vision-documents/variadic-generics.md

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -354,12 +354,52 @@ extension<Element...> (Element...): Hashable where Element: Hashable {
354354

355355
## The distinction between packs and tuples
356356

357-
Packs and tuples differ in the type system because a type pack itself is not a type while a tuple itself is a type. A type pack is composed of individual types, and type packs are only usable in positions that naturally accept a list of zero or more types, such as generic argument lists. On the other hand, a tuple can be used anywhere an individual type can be used. For example, a tuple can be used as a return value, but a value pack cannot:
357+
Packs and tuples differ in the type system because a type pack itself is not a type while a tuple itself is a type. A type pack is composed of individual types, and type packs are only usable in positions that naturally accept a list of zero or more types, such as generic argument lists. On the other hand, a tuple can be used anywhere an individual type can be used. The following code demonstrates the semantic differences between using a tuple value versus accessing its elements as a pack:
358358

359359
```swift
360-
func tuplify<T...>(_ t: T...) -> (T...) { return (t...) } // okay
360+
func printPack<U...>(_ u: U...) {
361+
print("u := {\(u...)}")
362+
}
363+
364+
func print4Ways<T...>(tuple: (T...), pack: T...) {
365+
print("Concatenating tuple with pack")
366+
printPacks(tuple, pack...)
367+
print("\n")
368+
369+
print("Concatenating tuple element pack with pack")
370+
printPacks(tuple.element..., pack...)
371+
print("\n")
372+
373+
print("Expanding tuple with pack")
374+
_ = (printPacks(tuple, pack)...)
375+
print("\n")
376+
377+
print("Expanding tuple element pack with pack")
378+
_ = (printPacks(tuple.element, pack)...)
379+
print("\n")
380+
}
381+
382+
print4Ways(tuple: (1, "hello", true), pack: 2, "world", false)
383+
```
384+
385+
The output of the above code is:
386+
387+
```
388+
Concatenating tuple with pack
389+
u := {(1, "hello", true), 2, "world", false}
390+
391+
Concatenating tuple element pack with pack
392+
u := {1, "hello", true, 2, "world", false}
393+
394+
Expanding tuple with pack
395+
u := {(1, "hello", true), 2}
396+
u := {(1, "hello", true), "world"}
397+
u := {(1, "hello", true), false}
361398
362-
func identity<T...>(_ t: T...) -> T... { return t... } // error
399+
Expanding tuple element pack with pack
400+
u := {1, 2}
401+
u := {"hello", "world"}
402+
u := {true, false}
363403
```
364404

365405
The concept of a pack is necessary in the language because though tuples can have an abstract length, there is a fundamental ambiguity between whether a tuple is meant to be used as a single type, or whether it was meant to be exploded to form a flattened comma-separated list of its elements:

0 commit comments

Comments
 (0)