Skip to content

Commit 3be8321

Browse files
committed
[stdlib] Fix the example in LazySequenceProtocol docs.
I'm not sure this code ever worked, but this new version does. Also includes some style revisions to the surrounding text.
1 parent a58db50 commit 3be8321

File tree

1 file changed

+88
-89
lines changed

1 file changed

+88
-89
lines changed

stdlib/public/core/LazySequence.swift

Lines changed: 88 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -10,123 +10,122 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
/// A sequence on which normally-eager operations such as `map` and
14-
/// `filter` are implemented lazily.
13+
/// A sequence on which normally-eager sequence operations are implemented
14+
/// lazily.
1515
///
1616
/// Lazy sequences can be used to avoid needless storage allocation
1717
/// and computation, because they use an underlying sequence for
18-
/// storage and compute their elements on demand. For example,
18+
/// storage and compute their elements on demand. For example, `doubled` in
19+
/// this code sample is a sequence containing the values `2`, `4`, and `6`.
1920
///
20-
/// [1, 2, 3].lazy.map { $0 * 2 }
21+
/// let doubled = [1, 2, 3].lazy.map { $0 * 2 }
2122
///
22-
/// is a sequence containing { `2`, `4`, `6` }. Each time an element
23-
/// of the lazy sequence is accessed, an element of the underlying
24-
/// array is accessed and transformed by the closure.
23+
/// Each time an element of the lazy sequence `doubled` is accessed, an element
24+
/// of the underlying array is accessed and transformed by the closure.
2525
///
26-
/// Sequence operations taking closure arguments, such as `map` and
27-
/// `filter`, are normally eager: they use the closure immediately and
28-
/// return a new array. Using the `lazy` property gives the standard
26+
/// Sequence operations that take closure arguments, such as `map(_:)` and
27+
/// `filter(_:)`, are normally eager: They use the closure immediately and
28+
/// return a new array. When you use the `lazy` property, you give the standard
2929
/// library explicit permission to store the closure and the sequence
3030
/// in the result, and defer computation until it is needed.
3131
///
32-
/// To add new lazy sequence operations, extend this protocol with
33-
/// methods that return lazy wrappers that are themselves
34-
/// `LazySequenceProtocol`s. For example, given an eager `scan`
35-
/// method defined as follows
32+
/// To add a new lazy sequence operation, extend this protocol with
33+
/// a method that returns a lazy wrapper that itself conforms to
34+
/// `LazySequenceProtocol`. For example, an eager `scan(_:_:)`
35+
/// method is defined as follows:
3636
///
3737
/// extension Sequence {
38-
/// /// Returns an array containing the results of
39-
/// ///
40-
/// /// p.reduce(initial, nextPartialResult)
41-
/// ///
42-
/// /// for each prefix `p` of `self`, in order from shortest to
43-
/// /// longest. For example:
44-
/// ///
45-
/// /// (1..<6).scan(0, +) // [0, 1, 3, 6, 10, 15]
46-
/// ///
47-
/// /// - Complexity: O(n)
48-
/// func scan<ResultElement>(
49-
/// _ initial: ResultElement,
50-
/// _ nextPartialResult: (ResultElement, Element) -> ResultElement
51-
/// ) -> [ResultElement] {
52-
/// var result = [initial]
53-
/// for x in self {
54-
/// result.append(nextPartialResult(result.last!, x))
38+
/// /// Returns an array containing the results of
39+
/// ///
40+
/// /// p.reduce(initial, nextPartialResult)
41+
/// ///
42+
/// /// for each prefix `p` of `self`, in order from shortest to
43+
/// /// longest. For example:
44+
/// ///
45+
/// /// (1..<6).scan(0, +) // [0, 1, 3, 6, 10, 15]
46+
/// ///
47+
/// /// - Complexity: O(n)
48+
/// func scan<ResultElement>(
49+
/// _ initial: ResultElement,
50+
/// _ nextPartialResult: (ResultElement, Element) -> ResultElement
51+
/// ) -> [ResultElement] {
52+
/// var result = [initial]
53+
/// for x in self {
54+
/// result.append(nextPartialResult(result.last!, x))
55+
/// }
56+
/// return result
5557
/// }
56-
/// return result
57-
/// }
5858
/// }
5959
///
60-
/// we can build a sequence that lazily computes the elements in the
61-
/// result of `scan`:
60+
/// You can build a sequence type that lazily computes the elements in the
61+
/// result of a scan:
6262
///
63-
/// struct LazyScanIterator<Base : IteratorProtocol, ResultElement>
64-
/// : IteratorProtocol {
65-
/// mutating func next() -> ResultElement? {
66-
/// return nextElement.map { result in
67-
/// nextElement = base.next().map { nextPartialResult(result, $0) }
68-
/// return result
69-
/// }
70-
/// }
71-
/// private var nextElement: ResultElement? // The next result of next().
72-
/// private var base: Base // The underlying iterator.
73-
/// private let nextPartialResult: (ResultElement, Base.Element) -> ResultElement
74-
/// }
75-
///
7663
/// struct LazyScanSequence<Base: Sequence, ResultElement>
77-
/// : LazySequenceProtocol // Chained operations on self are lazy, too
64+
/// : LazySequenceProtocol
7865
/// {
79-
/// func makeIterator() -> LazyScanIterator<Base.Iterator, ResultElement> {
80-
/// return LazyScanIterator(
81-
/// nextElement: initial, base: base.makeIterator(), nextPartialResult)
82-
/// }
83-
/// private let initial: ResultElement
84-
/// private let base: Base
85-
/// private let nextPartialResult:
86-
/// (ResultElement, Base.Element) -> ResultElement
66+
/// let initial: ResultElement
67+
/// let base: Base
68+
/// let nextPartialResult:
69+
/// (ResultElement, Base.Element) -> ResultElement
70+
///
71+
/// struct Iterator: IteratorProtocol {
72+
/// var base: Base.Iterator
73+
/// var nextElement: ResultElement?
74+
/// let nextPartialResult:
75+
/// (ResultElement, Base.Element) -> ResultElement
76+
///
77+
/// mutating func next() -> ResultElement? {
78+
/// return nextElement.map { result in
79+
/// nextElement = base.next().map {
80+
/// nextPartialResult(result, $0)
81+
/// }
82+
/// return result
83+
/// }
84+
/// }
85+
/// }
86+
///
87+
/// func makeIterator() -> Iterator {
88+
/// return Iterator(
89+
/// base: base.makeIterator(),
90+
/// nextElement: initial as ResultElement?,
91+
/// nextPartialResult: nextPartialResult)
92+
/// }
8793
/// }
8894
///
89-
/// and finally, we can give all lazy sequences a lazy `scan` method:
95+
/// Finally, you can give all lazy sequences a lazy `scan(_:_:)` method:
9096
///
9197
/// extension LazySequenceProtocol {
92-
/// /// Returns a sequence containing the results of
93-
/// ///
94-
/// /// p.reduce(initial, nextPartialResult)
95-
/// ///
96-
/// /// for each prefix `p` of `self`, in order from shortest to
97-
/// /// longest. For example:
98-
/// ///
99-
/// /// Array((1..<6).lazy.scan(0, +)) // [0, 1, 3, 6, 10, 15]
100-
/// ///
101-
/// /// - Complexity: O(1)
102-
/// func scan<ResultElement>(
103-
/// _ initial: ResultElement,
104-
/// _ nextPartialResult: (ResultElement, Element) -> ResultElement
105-
/// ) -> LazyScanSequence<Self, ResultElement> {
106-
/// return LazyScanSequence(
107-
/// initial: initial, base: self, nextPartialResult)
108-
/// }
98+
/// func scan<ResultElement>(
99+
/// _ initial: ResultElement,
100+
/// _ nextPartialResult: @escaping (ResultElement, Element) -> ResultElement
101+
/// ) -> LazyScanSequence<Self, ResultElement> {
102+
/// return LazyScanSequence<Self, ResultElement>(
103+
/// initial: initial, base: self, nextPartialResult: nextPartialResult)
104+
/// }
109105
/// }
110106
///
111-
/// - See also: `LazySequence`
107+
/// With this type and extension method, you can call `.lazy.scan(_:_:)` on any
108+
/// sequence to create a lazily computed scan. The resulting `LazyScanSequence`
109+
/// is itself lazy, too, so further sequence operations also defer computation.
112110
///
113-
/// - Note: The explicit permission to implement further operations
114-
/// lazily applies only in contexts where the sequence is statically
115-
/// known to conform to `LazySequenceProtocol`. Thus, side-effects such
116-
/// as the accumulation of `result` below are never unexpectedly
117-
/// dropped or deferred:
111+
/// The explicit permission to implement operations lazily applies
112+
/// only in contexts where the sequence is statically known to conform to
113+
/// `LazySequenceProtocol`. In the following example, because the extension
114+
/// applies only to `Sequence`, side-effects such as the accumulation of
115+
/// `result` are never unexpectedly dropped or deferred:
118116
///
119-
/// extension Sequence where Element == Int {
117+
/// extension Sequence where Element == Int {
120118
/// func sum() -> Int {
121-
/// var result = 0
122-
/// _ = self.map { result += $0 }
123-
/// return result
119+
/// var result = 0
120+
/// _ = self.map { result += $0 }
121+
/// return result
124122
/// }
125-
/// }
123+
/// }
126124
///
127-
/// [We don't recommend that you use `map` this way, because it
128-
/// creates and discards an array. `sum` would be better implemented
129-
/// using `reduce`].
125+
/// Don't actually use `map` for this purpose, however, since it creates
126+
/// and discards a resulting array. Instead, use `reduce` for summing
127+
/// operations, or `forEach` or a `for`-`in` loop for operations with side
128+
/// effects.
130129
public protocol LazySequenceProtocol : Sequence {
131130
/// A `Sequence` that can contain the same elements as this one,
132131
/// possibly with a simpler type.

0 commit comments

Comments
 (0)