-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[stdlib] Fix the example in LazySequenceProtocol docs. #24270
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 4 commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
3be8321
[stdlib] Fix the example in LazySequenceProtocol docs.
natecook1000 ab5846c
Shorten parameter name in doc example.
natecook1000 90f9dd4
Merge branch 'master' into nc_lazyscan_fix
natecook1000 06102a9
Minor additional revisions
natecook1000 f6547cc
Address feedback from @amartini51.
natecook1000 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -10,124 +10,124 @@ | |||||
// | ||||||
//===----------------------------------------------------------------------===// | ||||||
|
||||||
/// A sequence on which normally-eager operations such as `map` and | ||||||
/// `filter` are implemented lazily. | ||||||
/// A sequence on which normally-eager sequence operations are implemented | ||||||
/// lazily. | ||||||
/// | ||||||
/// Lazy sequences can be used to avoid needless storage allocation | ||||||
/// and computation, because they use an underlying sequence for | ||||||
/// storage and compute their elements on demand. For example, | ||||||
/// storage and compute their elements on demand. For example, `doubled` in | ||||||
/// this code sample is a sequence containing the values `2`, `4`, and `6`. | ||||||
/// | ||||||
/// [1, 2, 3].lazy.map { $0 * 2 } | ||||||
/// let doubled = [1, 2, 3].lazy.map { $0 * 2 } | ||||||
/// | ||||||
/// is a sequence containing { `2`, `4`, `6` }. Each time an element | ||||||
/// of the lazy sequence is accessed, an element of the underlying | ||||||
/// array is accessed and transformed by the closure. | ||||||
/// Each time an element of the lazy sequence `doubled` is accessed, an element | ||||||
/// of the underlying array is accessed and transformed by the closure. | ||||||
/// | ||||||
/// Sequence operations taking closure arguments, such as `map` and | ||||||
/// `filter`, are normally eager: they use the closure immediately and | ||||||
/// return a new array. Using the `lazy` property gives the standard | ||||||
/// Sequence operations that take closure arguments, such as `map(_:)` and | ||||||
/// `filter(_:)`, are normally eager: They use the closure immediately and | ||||||
/// return a new array. When you use the `lazy` property, you give the standard | ||||||
/// library explicit permission to store the closure and the sequence | ||||||
/// in the result, and defer computation until it is needed. | ||||||
/// | ||||||
/// To add new lazy sequence operations, extend this protocol with | ||||||
/// methods that return lazy wrappers that are themselves | ||||||
/// `LazySequenceProtocol`s. For example, given an eager `scan` | ||||||
/// method defined as follows | ||||||
/// ## Adding New Lazy Operations | ||||||
/// | ||||||
/// To add a new lazy sequence operation, extend this protocol with | ||||||
/// a method that returns a lazy wrapper that itself conforms to | ||||||
/// `LazySequenceProtocol`. For example, an eager `scan(_:_:)` | ||||||
/// method is defined as follows: | ||||||
/// | ||||||
/// extension Sequence { | ||||||
/// /// Returns an array containing the results of | ||||||
/// /// | ||||||
/// /// p.reduce(initial, nextPartialResult) | ||||||
/// /// | ||||||
/// /// for each prefix `p` of `self`, in order from shortest to | ||||||
/// /// longest. For example: | ||||||
/// /// | ||||||
/// /// (1..<6).scan(0, +) // [0, 1, 3, 6, 10, 15] | ||||||
/// /// | ||||||
/// /// - Complexity: O(n) | ||||||
/// func scan<ResultElement>( | ||||||
/// _ initial: ResultElement, | ||||||
/// _ nextPartialResult: (ResultElement, Element) -> ResultElement | ||||||
/// ) -> [ResultElement] { | ||||||
/// var result = [initial] | ||||||
/// for x in self { | ||||||
/// result.append(nextPartialResult(result.last!, x)) | ||||||
/// /// Returns an array containing the results of | ||||||
/// /// | ||||||
/// /// p.reduce(initial, nextPartialResult) | ||||||
/// /// | ||||||
/// /// for each prefix `p` of `self`, in order from shortest to | ||||||
/// /// longest. For example: | ||||||
/// /// | ||||||
/// /// (1..<6).scan(0, +) // [0, 1, 3, 6, 10, 15] | ||||||
/// /// | ||||||
/// /// - Complexity: O(n) | ||||||
/// func scan<Result>( | ||||||
/// _ initial: Result, | ||||||
/// _ nextPartialResult: (Result, Element) -> Result | ||||||
/// ) -> [Result] { | ||||||
/// var result = [initial] | ||||||
/// for x in self { | ||||||
/// result.append(nextPartialResult(result.last!, x)) | ||||||
/// } | ||||||
/// return result | ||||||
/// } | ||||||
/// return result | ||||||
/// } | ||||||
/// } | ||||||
/// | ||||||
/// we can build a sequence that lazily computes the elements in the | ||||||
/// result of `scan`: | ||||||
/// You can build a sequence type that lazily computes the elements in the | ||||||
/// result of a scan: | ||||||
/// | ||||||
/// struct LazyScanIterator<Base: IteratorProtocol, ResultElement> | ||||||
/// : IteratorProtocol { | ||||||
/// mutating func next() -> ResultElement? { | ||||||
/// return nextElement.map { result in | ||||||
/// nextElement = base.next().map { nextPartialResult(result, $0) } | ||||||
/// return result | ||||||
/// } | ||||||
/// } | ||||||
/// var nextElement: ResultElement? // The next result of next(). | ||||||
/// var base: Base // The underlying iterator. | ||||||
/// let nextPartialResult: (ResultElement, Base.Element) -> ResultElement | ||||||
/// } | ||||||
/// | ||||||
/// struct LazyScanSequence<Base: Sequence, ResultElement> | ||||||
/// : LazySequenceProtocol // Chained operations on self are lazy, too | ||||||
/// struct LazyScanSequence<Base: Sequence, Result> | ||||||
/// : LazySequenceProtocol | ||||||
/// { | ||||||
/// func makeIterator() -> LazyScanIterator<Base.Iterator, ResultElement> { | ||||||
/// return LazyScanIterator( | ||||||
/// nextElement: initial, base: base.makeIterator(), | ||||||
/// nextPartialResult: nextPartialResult) | ||||||
/// } | ||||||
/// let initial: ResultElement | ||||||
/// let base: Base | ||||||
/// let nextPartialResult: | ||||||
/// (ResultElement, Base.Element) -> ResultElement | ||||||
/// let initial: Result | ||||||
/// let base: Base | ||||||
/// let nextPartialResult: | ||||||
/// (Result, Base.Element) -> Result | ||||||
/// | ||||||
/// struct Iterator: IteratorProtocol { | ||||||
/// var base: Base.Iterator | ||||||
/// var nextElement: Result? | ||||||
/// let nextPartialResult: | ||||||
/// (Result, Base.Element) -> Result | ||||||
/// | ||||||
/// mutating func next() -> Result? { | ||||||
/// return nextElement.map { result in | ||||||
/// nextElement = base.next().map { | ||||||
/// nextPartialResult(result, $0) | ||||||
/// } | ||||||
/// return result | ||||||
/// } | ||||||
/// } | ||||||
/// } | ||||||
/// | ||||||
/// func makeIterator() -> Iterator { | ||||||
/// return Iterator( | ||||||
/// base: base.makeIterator(), | ||||||
/// nextElement: initial as Result?, | ||||||
/// nextPartialResult: nextPartialResult) | ||||||
/// } | ||||||
/// } | ||||||
/// | ||||||
/// and finally, we can give all lazy sequences a lazy `scan` method: | ||||||
/// Finally, you can give all lazy sequences a lazy `scan(_:_:)` method: | ||||||
/// | ||||||
/// extension LazySequenceProtocol { | ||||||
/// /// Returns a sequence containing the results of | ||||||
/// /// | ||||||
/// /// p.reduce(initial, nextPartialResult) | ||||||
/// /// | ||||||
/// /// for each prefix `p` of `self`, in order from shortest to | ||||||
/// /// longest. For example: | ||||||
/// /// | ||||||
/// /// Array((1..<6).lazy.scan(0, +)) // [0, 1, 3, 6, 10, 15] | ||||||
/// /// | ||||||
/// /// - Complexity: O(1) | ||||||
/// func scan<ResultElement>( | ||||||
/// _ initial: ResultElement, | ||||||
/// _ nextPartialResult: @escaping (ResultElement, Element) -> ResultElement | ||||||
/// ) -> LazyScanSequence<Self, ResultElement> { | ||||||
/// return LazyScanSequence( | ||||||
/// initial: initial, base: self, nextPartialResult: nextPartialResult) | ||||||
/// } | ||||||
/// func scan<Result>( | ||||||
/// _ initial: Result, | ||||||
/// _ nextPartialResult: @escaping (Result, Element) -> Result | ||||||
/// ) -> LazyScanSequence<Self, Result> { | ||||||
/// return LazyScanSequence( | ||||||
/// initial: initial, base: self, nextPartialResult: nextPartialResult) | ||||||
/// } | ||||||
/// } | ||||||
/// | ||||||
/// - See also: `LazySequence` | ||||||
/// With this type and extension method, you can call `.lazy.scan(_:_:)` on any | ||||||
/// sequence to create a lazily computed scan. The resulting `LazyScanSequence` | ||||||
/// is itself lazy, too, so further sequence operations also defer computation. | ||||||
/// | ||||||
/// - Note: The explicit permission to implement further operations | ||||||
/// lazily applies only in contexts where the sequence is statically | ||||||
/// known to conform to `LazySequenceProtocol`. Thus, side-effects such | ||||||
/// as the accumulation of `result` below are never unexpectedly | ||||||
/// dropped or deferred: | ||||||
/// The explicit permission to implement operations lazily applies | ||||||
/// only in contexts where the sequence is statically known to conform to | ||||||
/// `LazySequenceProtocol`. In the following example, because the extension | ||||||
/// applies only to `Sequence`, side-effects such as the accumulation of | ||||||
/// `result` are never unexpectedly dropped or deferred: | ||||||
/// | ||||||
/// extension Sequence where Element == Int { | ||||||
/// extension Sequence where Element == Int { | ||||||
/// func sum() -> Int { | ||||||
/// var result = 0 | ||||||
/// _ = self.map { result += $0 } | ||||||
/// return result | ||||||
/// var result = 0 | ||||||
/// _ = self.map { result += $0 } | ||||||
/// return result | ||||||
/// } | ||||||
/// } | ||||||
/// } | ||||||
/// | ||||||
/// [We don't recommend that you use `map` this way, because it | ||||||
/// creates and discards an array. `sum` would be better implemented | ||||||
/// using `reduce`]. | ||||||
/// Don't actually use `map` for this purpose, however, since it creates | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ASG uses "since" only in the temporal sense.
Suggested change
|
||||||
/// and discards the resulting array. Instead, use `reduce` for summing | ||||||
/// operations, or `forEach` or a `for`-`in` loop for operations with side | ||||||
/// effects. | ||||||
public protocol LazySequenceProtocol: Sequence { | ||||||
/// A `Sequence` that can contain the same elements as this one, | ||||||
/// possibly with a simpler type. | ||||||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this clearer in passive voice or active voice?