Skip to content

Commit af4ebb4

Browse files
invalidnameChris Adamsonphauslerbjlanier
authored
Provide doc comments for AsyncSequence and related types (#37383)
* First draft docs for iterator, sequence type. Also drop(while:), to get a feel for the AsyncSequence->AsyncSequence cases. * Source docs for contains and reduce. * Docs for methods in AsyncSequence. This covers all the methods that return a single value. Still working on the extension methods that return new sequences. * Early source docs for dropFirst(_:) and its type * Correct doc format for dropFirst(_:). * Prefix, plus some fixes. * Docs for prefix(while:). * Apply Philippe's snippet fixes. * First draft docs on the map sequences. Plus miscellaneous fixes throughout. * Show result of flatMap example. * More explicit cancellation guidance. * Convert snippets to trailing closures. * Correct misplaced doc comments. * Apply suggestions from code review Co-authored-by: Philippe Hausler <[email protected]> * Apply editorial feedback. * Apply additional editorial feedback. * Apply suggestions from code review Co-authored-by: bjlanier <[email protected]> * Apply further editorial feedback. Co-authored-by: Chris Adamson <[email protected]> Co-authored-by: Philippe Hausler <[email protected]> Co-authored-by: bjlanier <[email protected]>
1 parent 5b2f40a commit af4ebb4

16 files changed

+1043
-4
lines changed

stdlib/public/Concurrency/AsyncCompactMapSequence.swift

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,37 @@ import Swift
1414

1515
@available(SwiftStdlib 5.5, *)
1616
extension AsyncSequence {
17+
/// Creates an asynchronous sequence that maps the given closure over the
18+
/// asynchronous sequence’s elements, omitting results that don't return a
19+
/// value.
20+
///
21+
/// Use the `compactMap(_:)` method to transform every element received from
22+
/// a base asynchronous sequence, while also discarding any `nil` results
23+
/// from the closure. Typically, you use this to transform from one type of
24+
/// element to another.
25+
///
26+
/// In this example, an asynchronous sequence called `Counter` produces `Int`
27+
/// values from `1` to `5`. The closure provided to the `compactMap(_:)`
28+
/// method takes each `Int` and looks up a corresponding `String` from a
29+
/// `romanNumeralDict` dictionary. Because there is no key for `4`, the closure
30+
/// returns `nil` in this case, which `compactMap(_:)` omits from the
31+
/// transformed asynchronous sequence.
32+
///
33+
/// let romanNumeralDict: [Int : String] =
34+
/// [1: "I", 2: "II", 3: "III", 5: "V"]
35+
///
36+
/// let stream = Counter(howHigh: 5)
37+
/// .compactMap { romanNumeralDict[$0] }
38+
/// for await numeral in stream {
39+
/// print("\(numeral) ", terminator: " ")
40+
/// }
41+
/// // Prints: I II III V
42+
///
43+
/// - Parameter transform: A mapping closure. `transform` accepts an element
44+
/// of this sequence as its parameter and returns a transformed value of the
45+
/// same or of a different type.
46+
/// - Returns: An asynchronous sequence that contains, in order, the
47+
/// non-`nil` elements produced by the `transform` closure.
1748
@inlinable
1849
public __consuming func compactMap<ElementOfResult>(
1950
_ transform: @escaping (Element) async -> ElementOfResult?
@@ -22,6 +53,8 @@ extension AsyncSequence {
2253
}
2354
}
2455

56+
/// An asynchronous sequence that maps a given closure over the asynchronous
57+
/// sequence’s elements, omitting results that don't return a value.
2558
@available(SwiftStdlib 5.5, *)
2659
public struct AsyncCompactMapSequence<Base: AsyncSequence, ElementOfResult> {
2760
@usableFromInline
@@ -42,9 +75,15 @@ public struct AsyncCompactMapSequence<Base: AsyncSequence, ElementOfResult> {
4275

4376
@available(SwiftStdlib 5.5, *)
4477
extension AsyncCompactMapSequence: AsyncSequence {
78+
/// The type of element produced by this asynchronous sequence.
79+
///
80+
/// The compact map sequence produces whatever type of element its
81+
/// transforming closure produces.
4582
public typealias Element = ElementOfResult
83+
/// The type of iterator that produces elements of the sequence.
4684
public typealias AsyncIterator = Iterator
4785

86+
/// The iterator that produces elements of the compact map sequence.
4887
public struct Iterator: AsyncIteratorProtocol {
4988
public typealias Element = ElementOfResult
5089

@@ -63,6 +102,14 @@ extension AsyncCompactMapSequence: AsyncSequence {
63102
self.transform = transform
64103
}
65104

105+
/// Produces the next element in the compact map sequence.
106+
///
107+
/// This iterator calls `next()` on its base iterator; if this call returns
108+
/// `nil`, `next()` returns `nil`. Otherwise, `next()` calls the
109+
/// transforming closure on the received element, returning it if the
110+
/// transform returns a non-`nil` value. If the transform returns `nil`,
111+
/// this method continues to wait for further elements until it gets one
112+
/// that transforms to a non-`nil` value.
66113
@inlinable
67114
public mutating func next() async rethrows -> ElementOfResult? {
68115
while true {

stdlib/public/Concurrency/AsyncDropFirstSequence.swift

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,28 @@ import Swift
1414

1515
@available(SwiftStdlib 5.5, *)
1616
extension AsyncSequence {
17+
/// Omits a specified number of elements from the base asynchronous sequence,
18+
/// then passes through all remaining elements.
19+
///
20+
/// Use `dropFirst(_:)` when you want to drop the first *n* elements from the
21+
/// base sequence and pass through the remaining elements.
22+
///
23+
/// In this example, an asynchronous sequence called `Counter` produces `Int`
24+
/// values from `1` to `10`. The `dropFirst(_:)` method causes the modified
25+
/// sequence to ignore the values `0` through `4`, and instead emit `5` through `10`:
26+
///
27+
/// for await number in Counter(howHigh: 10).dropFirst(3) {
28+
/// print("\(number) ", terminator: " ")
29+
/// }
30+
/// // prints "4 5 6 7 8 9 10"
31+
///
32+
/// If the number of elements to drop exceeds the number of elements in the
33+
/// sequence, the result is an empty sequence.
34+
///
35+
/// - Parameter count: The number of elements to drop from the beginning of
36+
/// the sequence. `count` must be greater than or equal to zero.
37+
/// - Returns: An asynchronous sequence that drops the first `count`
38+
/// elements from the base sequence.
1739
@inlinable
1840
public __consuming func dropFirst(
1941
_ count: Int = 1
@@ -24,6 +46,8 @@ extension AsyncSequence {
2446
}
2547
}
2648

49+
/// An asynchronous sequence which omits a specified number of elements from the
50+
/// base asynchronous sequence, then passes through all remaining elements.
2751
@available(SwiftStdlib 5.5, *)
2852
public struct AsyncDropFirstSequence<Base: AsyncSequence> {
2953
@usableFromInline
@@ -41,9 +65,15 @@ public struct AsyncDropFirstSequence<Base: AsyncSequence> {
4165

4266
@available(SwiftStdlib 5.5, *)
4367
extension AsyncDropFirstSequence: AsyncSequence {
68+
/// The type of element produced by this asynchronous sequence.
69+
///
70+
/// The drop-first sequence produces whatever type of element its base
71+
/// iterator produces.
4472
public typealias Element = Base.Element
73+
/// The type of iterator that produces elements of the sequence.
4574
public typealias AsyncIterator = Iterator
4675

76+
/// The iterator that produces elements of the drop-first sequence.
4777
public struct Iterator: AsyncIteratorProtocol {
4878
@usableFromInline
4979
var baseIterator: Base.AsyncIterator
@@ -57,6 +87,14 @@ extension AsyncDropFirstSequence: AsyncSequence {
5787
self.count = count
5888
}
5989

90+
/// Produces the next element in the drop-first sequence.
91+
///
92+
/// Until reaching the number of elements to drop, this iterator calls
93+
/// `next()` on its base iterator and discards the result. If the base
94+
/// iterator returns `nil`, indicating the end of the sequence, this
95+
/// iterator returns `nil`. After reaching the number of elements to
96+
/// drop, this iterator passes along the result of calling `next()` on
97+
/// the base iterator.
6098
@inlinable
6199
public mutating func next() async rethrows -> Base.Element? {
62100
var remainingToDrop = count
@@ -80,6 +118,12 @@ extension AsyncDropFirstSequence: AsyncSequence {
80118

81119
@available(SwiftStdlib 5.5, *)
82120
extension AsyncDropFirstSequence {
121+
/// Omits a specified number of elements from the base asynchronous sequence,
122+
/// then passes through all remaining elements.
123+
///
124+
/// When you call `dropFirst(_:)` on an asynchronous sequence that is already
125+
/// an `AsyncDropFirstSequence`, the returned sequence simply adds the new
126+
/// drop count to the current drop count.
83127
@inlinable
84128
public __consuming func dropFirst(
85129
_ count: Int = 1
@@ -91,4 +135,3 @@ extension AsyncDropFirstSequence {
91135
return AsyncDropFirstSequence(base, dropping: self.count + count)
92136
}
93137
}
94-

stdlib/public/Concurrency/AsyncDropWhileSequence.swift

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,33 @@ import Swift
1414

1515
@available(SwiftStdlib 5.5, *)
1616
extension AsyncSequence {
17+
/// Omits elements from the base asynchronous sequence until a given closure
18+
/// returns false, after which it passes through all remaining elements.
19+
///
20+
/// Use `drop(while:)` to omit elements from an asynchronous sequence until
21+
/// the element received meets a condition you specify.
22+
///
23+
/// In this example, an asynchronous sequence called `Counter` produces `Int`
24+
/// values from `1` to `10`. The `drop(while:)` method causes the modified
25+
/// sequence to ignore received values until it encounters one that is
26+
/// divisible by `3`:
27+
///
28+
/// let stream = Counter(howHigh: 10)
29+
/// .drop { $0 % 3 != 0 }
30+
/// for await number in stream {
31+
/// print("\(number) ", terminator: " ")
32+
/// }
33+
/// // prints "3 4 5 6 7 8 9 10"
34+
///
35+
/// After the predicate returns `false`, the sequence never executes it again,
36+
/// and from then on the sequence passes through elements from its underlying
37+
/// sequence as-is.
38+
///
39+
/// - Parameter predicate: A closure that takes an element as a parameter and
40+
/// returns a Boolean value indicating whether to drop the element from the
41+
/// modified sequence.
42+
/// - Returns: An asynchronous sequence that skips over values from the
43+
/// base sequence until the provided closure returns `false`.
1744
@inlinable
1845
public __consuming func drop(
1946
while predicate: @escaping (Element) async -> Bool
@@ -22,6 +49,9 @@ extension AsyncSequence {
2249
}
2350
}
2451

52+
/// An asynchronous sequence which omits elements from the base sequence until a
53+
/// given closure returns false, after which it passes through all remaining
54+
/// elements.
2555
@available(SwiftStdlib 5.5, *)
2656
public struct AsyncDropWhileSequence<Base: AsyncSequence> {
2757
@usableFromInline
@@ -42,9 +72,16 @@ public struct AsyncDropWhileSequence<Base: AsyncSequence> {
4272

4373
@available(SwiftStdlib 5.5, *)
4474
extension AsyncDropWhileSequence: AsyncSequence {
75+
76+
/// The type of element produced by this asynchronous sequence.
77+
///
78+
/// The drop-while sequence produces whatever type of element its base
79+
/// sequence produces.
4580
public typealias Element = Base.Element
81+
/// The type of iterator that produces elements of the sequence.
4682
public typealias AsyncIterator = Iterator
4783

84+
/// The iterator that produces elements of the drop-while sequence.
4885
public struct Iterator: AsyncIteratorProtocol {
4986
@usableFromInline
5087
var baseIterator: Base.AsyncIterator
@@ -61,6 +98,14 @@ extension AsyncDropWhileSequence: AsyncSequence {
6198
self.predicate = predicate
6299
}
63100

101+
/// Produces the next element in the drop-while sequence.
102+
///
103+
/// This iterator calls `next()` on its base iterator and evaluates the
104+
/// result with the `predicate` closure. As long as the predicate returns
105+
/// `true`, this method returns `nil`. After the predicate returns `false`,
106+
/// for a value received from the base iterator, this method returns that
107+
/// value. After that, the iterator returns values received from its
108+
/// base iterator as-is, and never executes the predicate closure again.
64109
@inlinable
65110
public mutating func next() async rethrows -> Base.Element? {
66111
while let predicate = self.predicate {
@@ -76,6 +121,7 @@ extension AsyncDropWhileSequence: AsyncSequence {
76121
}
77122
}
78123

124+
/// Creates an instance of the drop-while sequence iterator.
79125
@inlinable
80126
public __consuming func makeAsyncIterator() -> Iterator {
81127
return Iterator(base.makeAsyncIterator(), predicate: predicate)

stdlib/public/Concurrency/AsyncFilterSequence.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,25 @@ import Swift
1414

1515
@available(SwiftStdlib 5.5, *)
1616
extension AsyncSequence {
17+
/// Creates an asynchronous sequence that contains, in order, the elements of
18+
/// the base sequence that satisfy the given predicate.
19+
///
20+
/// In this example, an asynchronous sequence called `Counter` produces `Int`
21+
/// values from `1` to `10`. The `filter(_:)` method returns `true` for even
22+
/// values and `false` for odd values, thereby filtering out the odd values:
23+
///
24+
/// let stream = Counter(howHigh: 10)
25+
/// .filter { $0 % 2 == 0 }
26+
/// for await number in stream {
27+
/// print("\(number) ", terminator: " ")
28+
/// }
29+
/// // Prints: 2 4 6 8 10
30+
///
31+
/// - Parameter isIncluded: A closure that takes an element of the
32+
/// asynchronous sequence as its argument and returns a Boolean value
33+
/// that indicates whether to include the element in the filtered sequence.
34+
/// - Returns: An asynchronous sequence that contains, in order, the elements
35+
/// of the base sequence that satisfy the given predicate.
1736
@inlinable
1837
public __consuming func filter(
1938
_ isIncluded: @escaping (Element) async -> Bool
@@ -22,6 +41,8 @@ extension AsyncSequence {
2241
}
2342
}
2443

44+
/// An asynchronous sequence that contains, in order, the elements of
45+
/// the base sequence that satisfy a given predicate.
2546
@available(SwiftStdlib 5.5, *)
2647
public struct AsyncFilterSequence<Base: AsyncSequence> {
2748
@usableFromInline
@@ -42,9 +63,15 @@ public struct AsyncFilterSequence<Base: AsyncSequence> {
4263

4364
@available(SwiftStdlib 5.5, *)
4465
extension AsyncFilterSequence: AsyncSequence {
66+
/// The type of element produced by this asynchronous sequence.
67+
///
68+
/// The filter sequence produces whatever type of element its base
69+
/// sequence produces.
4570
public typealias Element = Base.Element
71+
/// The type of iterator that produces elements of the sequence.
4672
public typealias AsyncIterator = Iterator
4773

74+
/// The iterator that produces elements of the filter sequence.
4875
public struct Iterator: AsyncIteratorProtocol {
4976
@usableFromInline
5077
var baseIterator: Base.AsyncIterator
@@ -61,6 +88,13 @@ extension AsyncFilterSequence: AsyncSequence {
6188
self.isIncluded = isIncluded
6289
}
6390

91+
/// Produces the next element in the filter sequence.
92+
///
93+
/// This iterator calls `next()` on its base iterator; if this call returns
94+
/// `nil`, `next()` returns nil. Otherwise, `next()` evaluates the
95+
/// result with the `predicate` closure. If the closure returns `true`,
96+
/// `next()` returns the received element; otherwise it awaits the next
97+
/// element from the base iterator.
6498
@inlinable
6599
public mutating func next() async rethrows -> Base.Element? {
66100
while true {

stdlib/public/Concurrency/AsyncFlatMapSequence.swift

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,41 @@ import Swift
1414

1515
@available(SwiftStdlib 5.5, *)
1616
extension AsyncSequence {
17-
@inlinable
17+
/// Creates an asynchronous sequence that concatenates the results of calling
18+
/// the given transformation with each element of this sequence.
19+
///
20+
/// Use this method to receive a single-level asynchronous sequence when your
21+
/// transformation produces an asynchronous sequence for each element.
22+
///
23+
/// In this example, an asynchronous sequence called `Counter` produces `Int`
24+
/// values from `1` to `5`. The transforming closure takes the received `Int`
25+
/// and returns a new `Counter` that counts that high. For example, when the
26+
/// transform receives `3` from the base sequence, it creates a new `Counter`
27+
/// that produces the values `1`, `2`, and `3`. The `flatMap(_:)` method
28+
/// "flattens" the resulting sequence-of-sequences into a single
29+
/// `AsyncSequence`.
30+
///
31+
/// let stream = Counter(howHigh: 5)
32+
/// .flatMap { Counter(howHigh: $0) }
33+
/// for await number in stream {
34+
/// print("\(number)", terminator: " ")
35+
/// }
36+
/// // Prints: 1 1 2 1 2 3 1 2 3 4 1 2 3 4 5
37+
///
38+
/// - Parameter transform: A mapping closure. `transform` accepts an element
39+
/// of this sequence as its parameter and returns an `AsyncSequence`.
40+
/// - Returns: A single, flattened asynchronous sequence that contains all
41+
/// elements in all the asychronous sequences produced by `transform`.
42+
@inlinable
1843
public __consuming func flatMap<SegmentOfResult: AsyncSequence>(
1944
_ transform: @escaping (Element) async -> SegmentOfResult
2045
) -> AsyncFlatMapSequence<Self, SegmentOfResult> {
2146
return AsyncFlatMapSequence(self, transform: transform)
2247
}
2348
}
2449

50+
/// An asynchronous sequence that concatenates the results of calling a given
51+
/// transformation with each element of this sequence.
2552
@available(SwiftStdlib 5.5, *)
2653
public struct AsyncFlatMapSequence<Base: AsyncSequence, SegmentOfResult: AsyncSequence> {
2754
@usableFromInline
@@ -42,9 +69,15 @@ public struct AsyncFlatMapSequence<Base: AsyncSequence, SegmentOfResult: AsyncSe
4269

4370
@available(SwiftStdlib 5.5, *)
4471
extension AsyncFlatMapSequence: AsyncSequence {
72+
/// The type of element produced by this asynchronous sequence.
73+
///
74+
/// The flat map sequence produces the type of element in the asynchronous
75+
/// sequence produced by the `transform` closure.
4576
public typealias Element = SegmentOfResult.Element
77+
/// The type of iterator that produces elements of the sequence.
4678
public typealias AsyncIterator = Iterator
4779

80+
/// The iterator that produces elements of the flat map sequence.
4881
public struct Iterator: AsyncIteratorProtocol {
4982
@usableFromInline
5083
var baseIterator: Base.AsyncIterator
@@ -67,6 +100,15 @@ extension AsyncFlatMapSequence: AsyncSequence {
67100
self.transform = transform
68101
}
69102

103+
/// Produces the next element in the flat map sequence.
104+
///
105+
/// This iterator calls `next()` on its base iterator; if this call returns
106+
/// `nil`, `next()` returns `nil`. Otherwise, `next()` calls the
107+
/// transforming closure on the received element, takes the resulting
108+
/// asynchronous sequence, and creates an asynchronous iterator from it.
109+
/// `next()` then consumes values from this iterator until it terminates.
110+
/// At this point, `next()` is ready to receive the next value from the base
111+
/// sequence.
70112
@inlinable
71113
public mutating func next() async rethrows -> SegmentOfResult.Element? {
72114
while !finished {

0 commit comments

Comments
 (0)