From d8c132f57f23359f33dcfe60d4a73c306da8f303 Mon Sep 17 00:00:00 2001 From: Ruiyang Sun Date: Wed, 26 Jun 2024 23:56:13 +0800 Subject: [PATCH] doc: refactor documentation (#6) --- .../BidirectionalAsyncStream.swift | 12 ++-- .../BidirectionalStream.docc/LandingPage.md | 64 +++++++++++++++++ .../BidirectionalSyncStream.swift | 16 +++-- .../BidirectionalSyncStream.md | 67 ----------------- .../SyncStream/SyncStream.docc/LandingPage.md | 28 ++++++++ .../SyncStream/SyncStream.docc/SyncStream.md | 72 ------------------- .../SyncStream.docc/SyncStreamClass.md | 17 +++-- .../SyncStream.docc/SyncStreamContinuation.md | 2 +- Sources/SyncStream/SyncStream.swift | 2 +- 9 files changed, 122 insertions(+), 158 deletions(-) create mode 100644 Sources/BidirectionalStream/BidirectionalStream.docc/LandingPage.md delete mode 100644 Sources/SyncStream/SyncStream.docc/BidirectionalSyncStream.md create mode 100644 Sources/SyncStream/SyncStream.docc/LandingPage.md delete mode 100644 Sources/SyncStream/SyncStream.docc/SyncStream.md diff --git a/Sources/BidirectionalStream/BidirectionalAsyncStream.swift b/Sources/BidirectionalStream/BidirectionalAsyncStream.swift index b4242fd..9ded538 100644 --- a/Sources/BidirectionalStream/BidirectionalAsyncStream.swift +++ b/Sources/BidirectionalStream/BidirectionalAsyncStream.swift @@ -25,10 +25,10 @@ public class BidirectionalAsyncStream { /// Creates a new `BidirectionalSyncStream`. /// /// - Parameters: - /// - YieldT: The type of the value to yield. - /// - SendT: The type of the value to send. - /// - ReturnT: The type of the value to return. - /// - build: A async closure that takes a `Continuation` and returns `Void`. + /// - The type of the value to yield. + /// - The type of the value to send. + /// - The type of the value to return. + /// - A async closure that takes a `Continuation` and returns `Void`. public init( _: YieldT.Type = YieldT.self, _: SendT.Type = SendT.self, @@ -203,6 +203,10 @@ public extension BidirectionalAsyncStream { /// /// - Parameters: /// - error: The error to throw. + /// - fileName: The name of the file where the error was thrown. + /// - functionName: The name of the function where the error was thrown. + /// - lineNumber: The line number where the error was thrown. + /// - columnNumber: The column number where the error was thrown. public func `throw`( error: any Error, fileName: String = #file, diff --git a/Sources/BidirectionalStream/BidirectionalStream.docc/LandingPage.md b/Sources/BidirectionalStream/BidirectionalStream.docc/LandingPage.md new file mode 100644 index 0000000..d1845b8 --- /dev/null +++ b/Sources/BidirectionalStream/BidirectionalStream.docc/LandingPage.md @@ -0,0 +1,64 @@ +# ``BidirectionalStream`` + +`BidirectionalStream` aims to bring features similar to Python's Generator to Swift. Users can generate values using `yield`, send values back with `send`, and close the stream by throwing a `StopIteration` error. + +## Overview + +Inspired by Python generators, which not only can use `yield` to produce values, but also can use `send` to receive values, and `return` to raise a `StopIteration` error and halt the stream, the ``BidirectionalSyncStream`` and ``BidirectionalAsyncStream`` in Swift offer similar features for synchronous and asynchronous operations respectively. + +For more information about the generator in python, See: [PEP 255](https://peps.python.org/pep-0255/), [PEP 342](https://peps.python.org/pep-0342/#new-generator-method-send-value), [Doc](https://docs.python.org/3/reference/expressions.html#generator-iterator-methods) + +## Getting Started + +In the following example, the stream uses the `send(_:)` method to send a value back to the stream, which is received by the `yield(_:)` return value. + +```swift +let stream = BidirectionalSyncStream { continuation in + var value = 0 + while true { + value = continuation.yield(value) + value += 1 + } +} + +try stream.next() // 0 start the stream +try stream.send(5) // 6 send value back to the stream, and get the next value +``` + +In the following example, when the stream's closure uses `return(_:)` to stop the streaming process, a `StopIteration` error containing the return value will be caught outside the closure. + +```swift +let stream = BidirectionalSyncStream { continuation in + var value = 0 + while true { + value = continuation.yield(value) + value += 1 + if value == 5 { + continuation.return("Stop") + } + } +} + +try stream.next() // 0 start the stream +do { + try stream.send(4) // Throw StopIteration error +} catch { + // get return value + print((error as! StopIteration).value) // "Stop" +} +``` + +## Topics + +### Supporting Types + ++ ``NoneType`` ++ ``StopIteration`` ++ ``Terminated`` ++ ``WrongStreamUse`` ++ ``AsyncSemaphore`` + +### BidirectionalStream + ++ ``BidirectionalSyncStream`` ++ ``BidirectionalAsyncStream`` diff --git a/Sources/BidirectionalStream/BidirectionalSyncStream.swift b/Sources/BidirectionalStream/BidirectionalSyncStream.swift index 40e921d..e499355 100644 --- a/Sources/BidirectionalStream/BidirectionalSyncStream.swift +++ b/Sources/BidirectionalStream/BidirectionalSyncStream.swift @@ -18,7 +18,7 @@ import SyncStream // MARK: - StopIteration -/// A special error to indicate the end of the stream. +/// A special error containing the return value to indicate the end of the stream. public struct StopIteration: Error { public var value: ReturnT } @@ -33,7 +33,7 @@ public struct WrongStreamUse: Error { // MARK: - Terminated /// An error to indicate that the stream has been terminated. -/// i.e. an error has occurred in the stream. +/// i.e. an error has occurred in the stream's inside closure. public struct Terminated: Error { /// The file name where the error occurred. public var fileName: String @@ -70,10 +70,10 @@ public class BidirectionalSyncStream { /// Creates a new `BidirectionalSyncStream`. /// /// - Parameters: - /// - YieldT: The type of the value to yield. - /// - SendT: The type of the value to send. - /// - ReturnT: The type of the value to return. - /// - build: A closure that takes a `Continuation` and returns `Void`. + /// - The type of the value to yield. + /// - The type of the value to send. + /// - The type of the value to return. + /// - A closure that takes a `Continuation` and returns `Void`. public init( _: YieldT.Type = YieldT.self, _: SendT.Type = SendT.self, @@ -250,6 +250,10 @@ public extension BidirectionalSyncStream { /// /// - Parameters: /// - error: The error to throw. + /// - fileName: The name of the file where the error was thrown. + /// - functionName: The name of the function where the error was thrown. + /// - lineNumber: The line number where the error was thrown. + /// - columnNumber: The column number where the error was thrown. public func `throw`( error: any Error, fileName: String = #file, diff --git a/Sources/SyncStream/SyncStream.docc/BidirectionalSyncStream.md b/Sources/SyncStream/SyncStream.docc/BidirectionalSyncStream.md deleted file mode 100644 index 4f6d254..0000000 --- a/Sources/SyncStream/SyncStream.docc/BidirectionalSyncStream.md +++ /dev/null @@ -1,67 +0,0 @@ -# ``BidirectionalSyncStream`` - -## Overview - -Inspired by the generator in python, which can not only use the `yield` to generate new value, but also can use `send` to sendback value and use `return` to throw `StopIteration` error to stop the stream. The `BidirectionalSyncStream` is a class that provides the same functionality in Swift. - -For more information about the generator in python, See: [PEP 255](https://peps.python.org/pep-0255/), [PEP 342](https://peps.python.org/pep-0342/#new-generator-method-send-value), [Doc](https://docs.python.org/3/reference/expressions.html#generator-iterator-methods) - -Like the `SyncStream` class, the `BidirectionalSyncStream` also use the `Continuation` to communicate with the stream. The `Continuation` provides two important method, the `yield(_:)` will yield a element to the stream, and then suspend for a value sended form the stream, the `return(_:)` will close the stream and throw a `StopIteration` error with a return value. - -In Stream side, User can use `next()` to start the stream, and this method will return the first yielded value. After the first `next()` invocation, user should to use `send(_:)` to control the stream, this method will send a value back, and then return next yielded value. After the stream is closed, aka the `return(_:)` is invoked, the `send(_:)` or `next()` will throw a `StopIteration` error, user can get the return value from the error. - -```swift -let stream = BidirectionalSyncStream { continuation in - var value = 0 - while true { - value = continuation.yield(value) - value += 1 - } -} - -try stream.next() // 0 start the stream -try stream.send(5) // 6 send value back to the stream, and get the next value -``` - -```swift -let stream = BidirectionalSyncStream { continuation in - var value = 0 - while true { - value = continuation.yield(value) - value += 1 - if value == 5 { - continuation.return("Stop") - } - } -} - -try stream.next() // 0 start the stream -do { - try stream.send(4) // Throw StopIteration error -} catch { - // get return value - print((error as! StopIteration).value) // "Stop" -} -``` - -## Topics - -### Supporting Types - -- ``NoneType`` - -### Errors - -- ``StopIteration`` -- ``WrongStreamUse`` - -### Building a BidirectionalSyncStream - -- ``init(_:_:_:_:)`` -- ``Continuation`` - -### Using a BidirectionalSyncStream - -- ``next()`` -- ``send(_:)`` -- ``toSyncStream()`` diff --git a/Sources/SyncStream/SyncStream.docc/LandingPage.md b/Sources/SyncStream/SyncStream.docc/LandingPage.md new file mode 100644 index 0000000..00bf1c3 --- /dev/null +++ b/Sources/SyncStream/SyncStream.docc/LandingPage.md @@ -0,0 +1,28 @@ +# ``SyncStream`` + +`SyncStream` is a class that generates a sequence of values, inspired by `AsyncStream` from the swift standard library. + +## Overview + +[`AsyncStream`](https://developer.apple.com/documentation/swift/asyncstream) offers a convenient method to create a sequence from a closure that invokes a continuation to generate elements. However, in certain cases, you may need to produce a sequence synchronously using a closure. To address this need, we introduce [`SyncStream`](syncstream/syncstream), which shares the same API as `AsyncStream` but operates synchronously. + +Here is a simple example of how to use `SyncStream`: + +```swift +let stream = SyncStream { continuation in + for i in 0 ..< 10 { + continuation.yield(i) + } + continuation.finish() +} + +for value in stream { + print(value, terminator: " ") +} +// 0 1 2 3 4 5 6 7 8 9 +``` + +## Topics + ++ ``SyncStream-class`` ++ ``SyncStream/Continuation`` diff --git a/Sources/SyncStream/SyncStream.docc/SyncStream.md b/Sources/SyncStream/SyncStream.docc/SyncStream.md deleted file mode 100644 index e42e64e..0000000 --- a/Sources/SyncStream/SyncStream.docc/SyncStream.md +++ /dev/null @@ -1,72 +0,0 @@ -# ``SyncStream`` - -SyncStream Package provides two classes, One is SyncStream which is similar to the swift `AsyncStream` but run in synchronous way. The other is `BidirectionalSyncStream` which is inspired by the generator in python, have the ability to send values back to the stream. - -## Overview - -### SyncStream - - [SyncStream](syncstream/syncstream) is inspired by Swift's [`AsyncStream`](https://developer.apple.com/documentation/swift/asyncstream) and offers a convenient way to generate a sequence using a closure, without the need to implement the `Sequence` protocol. - -Just like the [`AsyncStream`](https://developer.apple.com/documentation/swift/asyncstream) , the [SyncStream](syncstream/syncstream) also utilizes a class called [Continuation](syncstream/syncstream/continuation) to manage the production progress. The [Continuation](syncstream/syncstream/continuation) offers two main methods, [`yield(_:)`](syncstream/syncstream/continuation/yield(_:)) and [`finish`](syncstream/syncstream/continuation/finish()), similar to those in the [`AsyncStream`](https://developer.apple.com/documentation/swift/asyncstream), but operates synchronously. If you are familiar with Python, you can consider the [SyncStream](syncstream/syncstream) as a generator. - -```swift -let stream = SyncStream { continuation in - for i in 0..<10 { - continuation.yield(i) - } - continuation.finish() -} - -for value in stream { - print(value, terminator: " ") -} -// 0 1 2 3 4 5 6 7 8 9 -``` - -### BidirectionalSyncStream - -Inspired by the generator in python, which can not only use the `yield` to generate new value, but also can use `send` to sendback value and use `return` to throw `StopIteration` error to stop the stream. The `BidirectionalSyncStream` is a class that provides the same functionality in Swift. - -For more information about the generator in python, See: [PEP 255](https://peps.python.org/pep-0255/), [PEP 342](https://peps.python.org/pep-0342/#new-generator-method-send-value), [Doc](https://docs.python.org/3/reference/expressions.html#generator-iterator-methods) - -```swift -let stream = BidirectionalSyncStream { continuation in - var value = 0 - while true { - value = continuation.yield(value) - value += 1 - } -} - -try stream.next() // 0 start the stream -try stream.send(5) // 6 send value back to the stream, and get the next value -``` - -``` -let stream = BidirectionalSyncStream { continuation in - var value = 0 - while true { - value = continuation.yield(value) - value += 1 - if value == 5 { - continuation.return("Stop") - } - } -} - -try stream.next() // 0 start the stream -do { - try stream.send(4) // Throw StopIteration error -} catch { - // get return value - print((error as! StopIteration).value) // "Stop" -} -``` - -## Topics - -### Class - -- ``SyncStream-class`` -- ``BidirectionalSyncStream`` diff --git a/Sources/SyncStream/SyncStream.docc/SyncStreamClass.md b/Sources/SyncStream/SyncStream.docc/SyncStreamClass.md index d70a492..2b099f2 100644 --- a/Sources/SyncStream/SyncStream.docc/SyncStreamClass.md +++ b/Sources/SyncStream/SyncStream.docc/SyncStreamClass.md @@ -2,9 +2,11 @@ ## Overview -[SyncStream](syncstream/syncstream) is inspired by Swift's [`AsyncStream`](https://developer.apple.com/documentation/swift/asyncstream) and offers a convenient way to generate a sequence using a closure, without the need to implement the `Sequence` protocol. +[`AsyncStream`](https://developer.apple.com/documentation/swift/asyncstream) offers a convenient method to create a sequence from a closure that invokes a continuation to generate elements. However, in certain cases, you may need to produce a sequence synchronously using a closure. To address this need, we introduce [`SyncStream`](syncstream/syncstream), which shares the same API as `AsyncStream` but operates synchronously. -Just like the [`AsyncStream`](https://developer.apple.com/documentation/swift/asyncstream) , the [SyncStream](syncstream/syncstream) also utilizes a class called [Continuation](syncstream/syncstream/continuation) to manage the production progress. The [Continuation](syncstream/syncstream/continuation) offers two main methods, [`yield(_:)`](syncstream/syncstream/continuation/yield(_:)) and [`finish`](syncstream/syncstream/continuation/finish()), similar to those in the [`AsyncStream`](https://developer.apple.com/documentation/swift/asyncstream), but operates synchronously. If you are familiar with Python, you can consider the [SyncStream](syncstream/syncstream) as a generator. +In detail, the most common way to initialize a `SyncStream` is providing a closure that takes a `Continuation` argument. The `Continuation` class provides two key methods, `yield(_:)` and `finish()`, to manage the element production procedure. + +Because of the synchronous feature, the closure will not execute until you start iterating over the stream. ```swift let stream = SyncStream { continuation in @@ -15,7 +17,7 @@ let stream = SyncStream { continuation in } for value in stream { -print(value, terminator: " ") + print(value, terminator: " ") } // 0 1 2 3 4 5 6 7 8 9 ``` @@ -48,13 +50,14 @@ print(value, terminator: " ") - ``dropFirst(_:)`` - ``drop(while:)`` -- ``filter(_:)`` +- ``filter(_:)-6h5ix`` +- ``filter(_:)-7wb05`` ### Transforming a Sequence -- ``map(_:)-hk46`` -- ``map(_:)-5vrbe`` +- ``map(_:)`` - ``compactMap(_:)`` -- ``flatMap(_:)`` +- ``flatMap(_:)-uifn`` +- ``flatMap(_:)-5btn7`` - ``reduce(_:_:)`` - ``reduce(into:_:)`` diff --git a/Sources/SyncStream/SyncStream.docc/SyncStreamContinuation.md b/Sources/SyncStream/SyncStream.docc/SyncStreamContinuation.md index 9910fb2..0454d13 100644 --- a/Sources/SyncStream/SyncStream.docc/SyncStreamContinuation.md +++ b/Sources/SyncStream/SyncStream.docc/SyncStreamContinuation.md @@ -2,7 +2,7 @@ ## Overview -The Closure you provide to the `SyncStream` in `init(_:_:)` received an instance of this type when called. Use this continuation to yield element via method `yield(_)`, and finish the stream via method `finish()`. +The `Closure` used in the `SyncStream` takes an argument of `Continuation`, which provides the methods `yield(_:)` and `finish()` to produce elements and finish the stream. ## Topics diff --git a/Sources/SyncStream/SyncStream.swift b/Sources/SyncStream/SyncStream.swift index 3be33d5..3e42dbb 100644 --- a/Sources/SyncStream/SyncStream.swift +++ b/Sources/SyncStream/SyncStream.swift @@ -83,7 +83,7 @@ public class SyncStream: Sequence, IteratorProtocol { // MARK: Public /// Constructs an synchronous stream from the Element Type - /// - Parameter type: The Element Type + /// - Parameter of: The Element Type /// /// - Returns: A tuple containing the stream and its continuation. The continuation /// should be passed to the producer while the stream should be passed to the consumer.