### Search as You Type Example Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/AsyncAlgorithms.docc/Guides/FlatMapLatest.md A practical example demonstrating flatMapLatest for a search-as-you-type feature, where only results from the latest query are processed. ```swift let searchField = AsyncStream { continuation in // Emit search queries as user types continuation.yield("s") continuation.yield("sw") continuation.yield("swift") } let results = searchField.flatMapLatest { searchAPI(for: $0) } ``` -------------------------------- ### AsyncBytes Example Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/AsyncAlgorithms.docc/Guides/BufferedBytes.md Example of how to create an AsyncSequence of bytes using AsyncBufferedByteIterator. ```APIDOC ## AsyncBytes Example ### Description An example of an `AsyncSequence` that yields `UInt8` elements, backed by an asynchronous read source. ### Type Definition ```swift struct AsyncBytes: AsyncSequence { public typealias Element = UInt8 var handle: ReadableThing internal init(_ readable: ReadableThing) { handle = readable } public func makeAsyncIterator() -> AsyncBufferedByteIterator { return AsyncBufferedByteIterator(capacity: 16384) { // This runs once every 16384 invocations of next() return try await handle.read(into: buffer) } } } ``` ``` -------------------------------- ### Chain Usage Example Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0007-chain.md An example demonstrating how to use the chain function to prepend a preamble to a file's lines. ```APIDOC ## Chain Usage Example ### Description This example shows how to use the `chain` function to combine an array of strings (converted to an async sequence) with the lines from a file. ### Code ```swift let preamble = [ "// Some header to add as a preamble", "//", "" ].async let lines = chain(preamble, URL(fileURLWithPath: "/tmp/Sample.swift").lines) for try await line in lines { print(line) } ``` ``` -------------------------------- ### Example Usage of Zip Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0001-zip.md Demonstrates how to use the zip function to combine two asynchronous sequences of URL lines. ```APIDOC ## Example Usage This example shows how to zip two asynchronous sequences representing lines from different URL feeds. ```swift let appleFeed = URL(string: "http://www.example.com/ticker?symbol=AAPL")!.lines let nasdaqFeed = URL(string: "http://www.example.com/ticker?symbol=^IXIC")!.lines for try await (apple, nasdaq) in zip(appleFeed, nasdaqFeed) { print("APPL: \(apple) NASDAQ: \(nasdaq)") } ``` ``` -------------------------------- ### AsyncBytes Example Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0008-bytes.md Demonstrates how to create an AsyncSequence of bytes using AsyncBufferedByteIterator. ```APIDOC ## Struct AsyncBytes ### Description An `AsyncSequence` that provides bytes from a readable source. ### Initializer ```swift internal init(_ readable: ReadableThing) ``` Initializes `AsyncBytes` with a readable source. ### Method ```swift public func makeAsyncIterator() -> AsyncBufferedByteIterator ``` Returns an `AsyncBufferedByteIterator` configured to read from the `handle`. ### Example Usage ```swift struct AsyncBytes: AsyncSequence { public typealias Element = UInt8 var handle: ReadableThing internal init(_ readable: ReadableThing) { handle = readable } public func makeAsyncIterator() -> AsyncBufferedByteIterator { return AsyncBufferedByteIterator(capacity: 16384) { buffer in // This runs once every 16384 invocations of next() return try await handle.read(into: buffer) } } } ``` ``` -------------------------------- ### Combine Latest Usage Example Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/AsyncAlgorithms.docc/Guides/CombineLatest.md An example demonstrating how to use combineLatest with two asynchronous sequences. ```APIDOC ## Combine Latest Usage Example ### Description This example shows how to use the `combineLatest` function to combine two asynchronous sequences representing stock feeds. ### Code Example ```swift let appleFeed = URL("http://www.example.com/ticker?symbol=AAPL").lines let nasdaqFeed = URL("http://www.example.com/ticker?symbol=^IXIC").lines for try await (apple, nasdaq) in combineLatest(appleFeed, nasdaqFeed) { print("AAPL: \(apple) NASDAQ: \(nasdaq)") } ``` ### Expected Output Behavior The combined output will reflect the latest values from both `appleFeed` and `nasdaqFeed`. If one feed terminates before producing its first element, the combined sequence will also terminate. After the first element is produced, the combined sequence terminates only when all base sequences terminate. Errors thrown by any base sequence will be propagated to the combined sequence. ``` -------------------------------- ### Initialize Dictionary with Unique Keys Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/AsyncAlgorithms.docc/Guides/Collections.md Example showing how to initialize a `Dictionary` using the `uniqueKeysWithValues` initializer with zipped keys and values. ```swift let table = await Dictionary(uniqueKeysWithValues: zip(keys, values)) ``` -------------------------------- ### Initialize Data from Resource Bytes Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/AsyncAlgorithms.docc/Guides/Collections.md Example demonstrating how to initialize `Data` from the resource bytes of a URL, utilizing the new asynchronous initializer for `RangeReplaceableCollection`. ```swift let contents = try await Data(URL(fileURLWithPath: "/tmp/example.bin").resourceBytes) ``` -------------------------------- ### Example: Chunking Numbers by Group Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0013-chunk.md This example demonstrates chunking an async sequence of numbers. Elements are grouped if the current element is less than or equal to the previous one. The output shows the resulting chunks. ```swift let chunks = numbers.chunked { $0 <= $1 } for await numberChunk in chunks { print(numberChunk) } ``` ```swift [10, 20, 30] [10, 40, 40] [10, 20] ``` -------------------------------- ### Dynamic Configuration Data Loading Example Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/AsyncAlgorithms.docc/Guides/FlatMapLatest.md Demonstrates using flatMapLatest to reload data whenever configuration settings change, ensuring data consistency with the latest settings. ```swift let settings = userSettingsStream let data = settings.flatMapLatest { loadData(with: $0) } ``` -------------------------------- ### Example Usage of FlatMapLatest Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/AsyncAlgorithms.docc/Guides/FlatMapLatest.md Demonstrates how flatMapLatest cancels previous inner sequences when new elements arrive from the outer sequence. This example simulates a search-as-you-type scenario. ```swift let searchQuery = AsyncStream { continuation in // User types into search field continuation.yield("swi") try? await Task.sleep(for: .milliseconds(100)) continuation.yield("swift") try? await Task.sleep(for: .milliseconds(100)) continuation.yield("swift async") continuation.finish() } let searchResults = searchQuery.flatMapLatest { query in performSearch(query) // Returns AsyncSequence } for try await result in searchResults { print(result) // Only shows results from "swift async" } ``` -------------------------------- ### Example: Chunking Names by First Letter Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0013-chunk.md This example demonstrates chunking an async sequence of names by their first letter. The output iterates through each first letter and the names associated with it. ```swift let names = URL(fileURLWithPath: "/tmp/names.txt").lines let groupedNames = names.chunked(on: \.first!) for try await (firstLetter, names) in groupedNames { print(firstLetter) for name in names { print(" ", name) } } ``` -------------------------------- ### Example Usage of Throttle Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0014-rate-limits.md Demonstrates how to apply the throttle operation to an asynchronous sequence to ensure a minimum interval between emitted events. ```swift fastEvents.throttle(for: .seconds(1)) ``` -------------------------------- ### FlatMapLatest with User Actions Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0018-flatMapLatest.md A concise example demonstrating the application of flatMapLatest to handle user actions, ensuring that only the most recent action's performance is considered. ```swift userActions.flatMapLatest { performAction($0) } ``` -------------------------------- ### Initialize Set with a Prefix of an AsyncSequence Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/AsyncAlgorithms.docc/Guides/Collections.md Example demonstrating how to initialize a `Set` from the first 10 elements of an asynchronous sequence using the `prefix` operation and the new initializer. ```swift let allItems = await Set(items.prefix(10)) ``` -------------------------------- ### Location-Based Data Fetching Example Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/AsyncAlgorithms.docc/Guides/FlatMapLatest.md Shows how flatMapLatest can be used to fetch data relevant to the latest location update, cancelling previous data fetches. ```swift let locationUpdates = CLLocationManager.shared.locationUpdates let nearbyPlaces = locationUpdates.flatMapLatest { fetchNearbyPlaces(at: $0) } ``` -------------------------------- ### Chunk Bytes into Data Instances Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/AsyncAlgorithms.docc/Guides/Chunked.md Example of chunking a sequence of bytes into `Data` instances, each with a maximum size of 1024 bytes. ```swift let packets = bytes.chunks(ofCount: 1024, into: Data.self) for try await packet in packets { write(packet) } ``` -------------------------------- ### Concatenate AsyncSequences with Joined Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0004-joined.md Example demonstrating how to use the `joined()` algorithm to concatenate two `AsyncSequence`s (URL lines) into a single sequence for iteration. ```swift let appleFeed = URL("http://www.example.com/ticker?symbol=AAPL").lines let nasdaqFeed = URL("http://www.example.com/ticker?symbol=^IXIC").lines for try await line in [appleFeed, nasdaqFeed].async.joined() { print("\(line)") } ``` -------------------------------- ### AsyncSequence Validation Example Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncSequenceValidation/AsyncSequenceValidation.docc/Validation.md An example demonstrating the usage of the validate function with a closure that defines input, processing, and expected output for an asynchronous sequence. ```swift validate { "a--b--c---|" $0.inputs[0].map { item in await Task { item.capitalized }.value } "A--B--C---|" } ``` -------------------------------- ### Combine Latest Usage Example Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0006-combineLatest.md Demonstrates how to use the combineLatest function with two asynchronous sequences. ```APIDOC ## POST /api/users ### Description This endpoint allows for the creation of new user resources. ### Method POST ### Endpoint /api/users ### Parameters #### Query Parameters - **limit** (integer) - Optional - The maximum number of users to return. #### Request Body - **username** (string) - Required - The desired username for the new user. - **email** (string) - Required - The email address of the new user. - **age** (integer) - Optional - The age of the new user. ### Request Example ```json { "username": "johndoe", "email": "john.doe@example.com", "age": 30 } ``` ### Response #### Success Response (201) - **id** (string) - The unique identifier for the newly created user. - **username** (string) - The username of the created user. - **email** (string) - The email address of the created user. - **createdAt** (string) - The timestamp when the user was created. #### Response Example ```json { "id": "user-12345", "username": "johndoe", "email": "john.doe@example.com", "createdAt": "2023-10-27T10:00:00Z" } ``` ``` -------------------------------- ### Example Usage of Debounce Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0014-rate-limits.md Demonstrates how to apply the debounce operation to an asynchronous sequence to limit the rate of emitted events. ```swift fastEvents.debounce(for: .seconds(1)) ``` -------------------------------- ### Example Usage of Merge Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0002-merge.md Demonstrates merging two asynchronous sequences representing stock feeds. The output prints ticker information as it becomes available from either feed. ```swift let appleFeed = URL(string: "http://www.example.com/ticker?symbol=AAPL")!.lines.map { "AAPL: " + $0 } let nasdaqFeed = URL(string:"http://www.example.com/ticker?symbol=^IXIC")!.lines.map { "^IXIC: " + $0 } for try await ticker in merge(appleFeed, nasdaqFeed) { print(ticker) } ``` -------------------------------- ### Example: Chunking Numbers by Group (Swift) Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/AsyncAlgorithms.docc/Guides/Chunked.md Demonstrates chunking an asynchronous sequence of numbers where elements are grouped if the current element is less than or equal to the previous one. The output shows the resulting chunks. ```swift let chunks = numbers.chunked { $0 <= $1 } for await numberChunk in chunks { print(numberChunk) } ``` -------------------------------- ### AsyncBytes AsyncSequence Implementation Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0008-bytes.md An example of how to implement an AsyncSequence for bytes using AsyncBufferedByteIterator. It initializes the iterator with a specified capacity and a read function. ```swift struct AsyncBytes: AsyncSequence { public typealias Element = UInt8 var handle: ReadableThing internal init(_ readable: ReadableThing) { handle = readable } public func makeAsyncIterator() -> AsyncBufferedByteIterator { return AsyncBufferedByteIterator(capacity: 16384) { // This runs once every 16384 invocations of next() return try await handle.read(into: buffer) } } } ``` -------------------------------- ### AsyncWriter write() Method Example Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncStreaming/NNNN-async-streaming.md Demonstrates how to use the `write` method of an AsyncWriter. The closure appends elements to the provided buffer, and the writer manages the buffer and writing operation. ```swift /// Provides a buffer for writing elements to the destination. /// /// The writer supplies a buffer, sized by the implementation, that /// `body` uses to append elements. The writer manages the buffer /// allocation and handles the writing operation once `body` completes. /// Oversized payloads are split across multiple calls. /// /// - Parameter body: A closure that receives a buffer for appending elements /// to write. The closure returns a result of type `Return`. /// /// ## Example /// /// ```swift /// var writer: SomeAsyncWriter = ... /// /// try await writer.write { buffer in /// for item in items { /// buffer.append(item) /// } /// return buffer.count /// } /// ``` /// /// - Returns: The value the body closure returns. /// /// - Throws: An `EitherError` containing either a `WriteFailure` from the write operation /// or a `Failure` from the body closure. mutating func write( _ body: (inout Buffer) async throws(Failure) -> Return ) async throws(EitherError) -> Return ``` -------------------------------- ### Inclusive Reductions Running Tally Example Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/AsyncAlgorithms.docc/Guides/Reductions.md Illustrates using inclusive reductions to calculate a running tally by summing elements. For input numbers 1, 2, 3, 4, the output would be 1, 3, 6, 10. ```swift numbers.reductions { $0 + $1 } ``` -------------------------------- ### Share Async Sequence with Unbounded Buffering Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0016-share.md Demonstrates sharing an asynchronous sequence with an unbounded buffer policy. This example shows two tasks concurrently iterating over the same shared sequence, illustrating potential out-of-order execution between tasks but guaranteed order within each task's iteration. Use this when the order of consumption does not need to strictly drive the producer, and buffering can accommodate varying consumption rates. ```swift let exampleSource = [0, 1, 2, 3, 4].async.share(bufferingPolicy: .unbounded) let t1 = Task { for await element in exampleSource { if element == 0 { try? await Task.sleep(for: .seconds(1)) } print("Task 1", element) } } let t2 = Task { for await element in exampleSource { if element == 3 { try? await Task.sleep(for: .seconds(1)) } print("Task 2", element) } } await t1.value await t2.value ``` -------------------------------- ### Basic AsyncChannel Usage Example Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0012-channel.md Demonstrates sending calculated results to a consumer task. The `send(_:)` call suspends until the consumer requests the next item, enforcing back pressure. ```swift let channel = AsyncChannel() Task { while let resultOfLongCalculation = doLongCalculations() { await channel.send(resultOfLongCalculation) } channel.finish() } for await calculationResult in channel { print(calculationResult) } ``` -------------------------------- ### Merge Usage Example Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0002-merge.md Demonstrates how to use the `merge` function to combine two asynchronous sequences (e.g., fetching stock ticker data) into a single sequence for iteration. ```APIDOC ## Merge Usage Example ### Description This example shows how to use the `merge` function to combine two asynchronous sequences, `appleFeed` and `nasdaqFeed`, into a single sequence that prints merged ticker information. ### Code ```swift let appleFeed = URL(string: "http://www.example.com/ticker?symbol=AAPL")!.lines.map { "AAPL: " + $0 } let nasdaqFeed = URL(string:"http://www.example.com/ticker?symbol=^IXIC")!.lines.map { "^IXIC: " + $0 } for try await ticker in merge(appleFeed, nasdaqFeed) { print(ticker) } ``` ### Expected Output Given sample inputs, the merged output might look like this: | Timestamp | appleFeed | nasdaqFeed | merged output | | ----------- | --------- | ---------- | --------------- | | 11:40 AM | 173.91 | | AAPL: 173.91 | | 12:25 AM | | 14236.78 | ^IXIC: 14236.78 | | 12:40 AM | | 14218.34 | ^IXIC: 14218.34 | | 1:15 PM | 173.00 | | AAPL: 173.00 | ``` -------------------------------- ### Bidirectional Streaming with Unstructured Task Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncStreaming/NNNN-async-streaming.md This example demonstrates a common but problematic pattern for bidirectional streaming using AsyncSequence. It forces the use of an unstructured task to continue iterating the input after the method returns, breaking structured concurrency guarantees. ```swift func bidirectionalStreaming( input: some AsyncSequence ) async throws -> some AsyncSequence { // The output sequence can produce values before input is fully consumed. // This forces an unstructured task to continue iterating the input // after this method returns. Task { for await byte in input { // Send byte } } return SomeOutputSequence() } ``` -------------------------------- ### Exclusive Reductions Mutation Example Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/AsyncAlgorithms.docc/Guides/Reductions.md Demonstrates using exclusive reductions with mutation to append characters to a string asynchronously. The intermediate results are 'a', 'ab', 'abc' if the input characters are 'a', 'b', 'c'. ```swift characters.reductions(into: "") { $0.append($1) } ``` -------------------------------- ### Create Async Channel and Source Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0016-mutli-producer-single-consumer-channel.md Initializes a new `MultiProducerSingleConsumerAsyncChannel` and its `Source`. The source is for producers and the channel for consumers. ```swift public static func makeChannel< Element, Failure >(of elementType: Element.Type = Element.self, throwing failureType: Failure.Type = Never.self, backpressureStrategy: Source.BackpressureStrategy ) -> ChannelAndStream ``` -------------------------------- ### Validation for Merged AsyncSequences Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncSequenceValidation/AsyncSequenceValidation.docc/Validation.md Validate the behavior of merged asynchronous sequences. This example shows how to specify multiple inputs and their combined expected output. ```swift validate { "a-c--f-|" "-b-de-g|" merge($0.inputs[0], $0.inputs[1]) "abcdefg|" } ``` -------------------------------- ### Basic Usage Without FlatMapLatest Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0018-flatMapLatest.md Demonstrates a scenario without flatMapLatest where all network requests complete, potentially leading to wasted resources and stale results. ```swift let searchQueries = userInputField.textChanges // Without flatMapLatest - all requests complete, wasting resources for await query in searchQueries { let results = try await searchAPI(query) displayResults(results) // May display stale results } ``` -------------------------------- ### Intersperse values in an async sequence Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/AsyncAlgorithms.docc/Guides/Intersperse.md Use `interspersed(with:)` to insert a value between each element. The output will include the separator. This example prints the interspersed sequence. ```swift let numbers = [1, 2, 3].async.interspersed(with: 0) for await number in numbers { print(number) } // prints 1 0 2 0 3 ``` -------------------------------- ### Notify Producer of Task Cancellation Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0016-mutli-producer-single-consumer-channel.md The producer can be notified of termination via the `onTerminationCallback`. This example shows termination due to task cancellation of a consumer task. ```swift // Termination through task cancellation let channelAndSource = MultiProducerSingleConsumerAsyncChannel.makeChannel( of: Int.self, backpressureStrategy: .watermark(low: 2, high: 4) ) var channel = consume channelAndSource.channel var source = consume channelAndSource.source source.setOnTerminationCallback { print("Terminated") } let task = Task { await channel.next() } task.cancel() // Prints Terminated ``` -------------------------------- ### Create Dictionary from adjacent pairs Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0005-adjacent-pairs.md Shows how to use adjacentPairs() with the Dictionary initializer to create a dictionary from lines of a URL, where each line becomes a key-value pair. ```swift Dictionary(uniqueKeysWithValues: url.lines.adjacentPairs()) ``` -------------------------------- ### Dictionary Initializers Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/AsyncAlgorithms.docc/Guides/Collections.md Provides asynchronous initializers for Dictionary to create dictionaries from AsyncSequences of key-value pairs, supporting unique key handling and value combination. ```APIDOC ## Dictionary Initializers ### Description Adds asynchronous, rethrowing initializers to `Dictionary` to construct dictionaries from `AsyncSequence`s of key-value pairs. These initializers facilitate asynchronous key uniquing and value combination. ### Method 1. `init(uniqueKeysWithValues keysAndValues: S) async rethrows` - Initializes a dictionary from an `AsyncSequence` of key-value pairs, ensuring unique keys. 2. `init(_ keysAndValues: S, uniquingKeysWith combine: (Value, Value) async throws -> Value) async rethrows` - Initializes a dictionary from an `AsyncSequence` of key-value pairs, using a provided asynchronous closure to resolve duplicate keys. 3. `init(grouping values: S, by keyForValue: (S.Element) async throws -> Key) async rethrows` - Initializes a dictionary by grouping elements from an `AsyncSequence` based on a provided asynchronous key-extraction closure. The dictionary's values will be arrays of elements. ### Endpoint N/A (Extension Methods) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```swift // Example 1: Unique keys let dictionary1 = await Dictionary(uniqueKeysWithValues: asyncSequenceOfPairs) // Example 2: Uniquing keys let dictionary2 = await Dictionary(asyncSequenceOfPairs) { old, new in new } // Example 3: Grouping values let dictionary3 = await Dictionary(grouping: asyncSequenceOfValues) { await getKey(for: $0) } ``` ### Response #### Success Response (200) Initializes the dictionary with elements processed from the `AsyncSequence` according to the chosen initializer strategy. #### Response Example ```swift // Example usage: let myDictionary = await Dictionary(uniqueKeysWithValues: asyncKeyValuePairs) ``` ``` -------------------------------- ### Concise Switching Behavior with FlatMapLatest Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/AsyncAlgorithms.docc/Guides/FlatMapLatest.md Illustrates a common pattern using flatMapLatest to switch to new asynchronous operations based on incoming elements, cancelling previous operations. ```swift userInput.flatMapLatest { input in fetchDataFromNetwork(input) } ``` -------------------------------- ### Initialize Dictionary from AsyncSequence of Key-Value Pairs Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/AsyncAlgorithms.docc/Guides/Collections.md Provides asynchronous initializers for `Dictionary` to construct it from an `AsyncSequence` of key-value pairs. Supports unique keys and custom combining logic for duplicate keys. ```swift extension Dictionary { public init( uniqueKeysWithValues keysAndValues: S ) async rethrows where S.Element == (Key, Value) public init( _ keysAndValues: S, uniquingKeysWith combine: (Value, Value) async throws -> Value ) async rethrows where S.Element == (Key, Value) public init( grouping values: S, by keyForValue: (S.Element) async throws -> Key ) async rethrows where Value == [S.Element] } ``` -------------------------------- ### Chunk by Count or Signal with AsyncTimerSequence Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/AsyncAlgorithms.docc/Guides/Chunked.md Chunks an asynchronous sequence by count or by a timer. The timer starts when the iterator is first called and emits on a regular cadence, unaffected by count-based emissions. ```swift extension AsyncSequence { public func chunked( by timer: AsyncTimerSequence, into: Collected.Type ) -> AsyncChunksOfCountOrSignalSequence> where Collected.Element == Element public func chunked( by timer: AsyncTimerSequence ) -> AsyncChunksOfCountOrSignalSequence> } ``` -------------------------------- ### Emit Chunks by Count or Signal in Swift Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0013-chunk.md Emits chunks when the count is reached or the signal emits. A signal emission resets the accumulated count. When using `AsyncTimerSequence` as a signal, it starts when the iterator is first called. ```swift let packets = bytes.chunks(ofCount: 1024 or: .repeating(every: .seconds(1)), into: Data.self) for try await packet in packets { write(packet) } ``` -------------------------------- ### Intersperse with an empty async sequence Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/AsyncAlgorithms.docc/Guides/Intersperse.md When `interspersed(with:)` is used on an empty asynchronous sequence, the resulting sequence is also empty. This example shows that awaiting the array conversion of an empty interspersed sequence results in an empty array. ```swift let empty = [].async.interspersed(with: 0) // await Array(empty) == [] ``` -------------------------------- ### Share AsyncSequence with .bounded Policy Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0016-share.md Demonstrates the .bounded(1) policy, which enforces consumption to prevent sides from being too far apart. Consumers must wait for the buffer count to drop below the specified value. ```swift let exampleSource = [0, 1, 2, 3, 4].async.share(bufferingPolicy: .bounded(1)) let t1 = Task { for await element in exampleSource { if element == 0 { try? await Task.sleep(for: .seconds(1)) } print("Task 1", element) } } let t2 = Task { for await element in exampleSource { if element == 3 { try? await Task.sleep(for: .seconds(1)) } print("Task 2", element) } } await t1.value await t2.value ``` -------------------------------- ### Initialize SetAlgebra from AsyncSequence Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/AsyncAlgorithms.docc/Guides/Collections.md Use this initializer to create any `SetAlgebra` (like `Set` or `OptionSet`) from an `AsyncSequence`. It is asynchronous and rethrows errors from the source sequence. ```swift extension SetAlgebra { public init( _ source: Source ) async rethrows where Source.Element == Element } ``` -------------------------------- ### Create MultiProducerSingleConsumerAsyncChannel Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0016-mutli-producer-single-consumer-channel.md Instantiate a channel and its source using makeChannel. The source is used for sending values. ```swift let channelAndSource = MultiProducerSingleConsumerAsyncChannel.makeChannel( of: Int.self, backpressureStrategy: .watermark(low: 2, high: 4) ) // The channel and source can be extracted from the returned type let channel = consume channelAndSource.channel let source = consume channelAndSource.source ``` -------------------------------- ### Chunking by Count or Signal Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/AsyncAlgorithms.docc/Guides/Chunked.md This API allows chunking an asynchronous sequence when either a specified count is reached or a signal asynchronous sequence emits. When a signal causes a chunk to be emitted, the accumulated element count is reset. Timers used as signals start when the iterator is first called. ```APIDOC ## Chunking by Count or Signal ### Description Chunks an asynchronous sequence when either a specified count is reached or a signal asynchronous sequence emits. When a signal causes a chunk to be emitted, the accumulated element count is reset. Timers used as signals start when the iterator is first called. ### Method `chunks(ofCount:or:into:)` `chunks(ofCount:or:) `chunked(by:into:)` `chunked(by:) ### Endpoint N/A (Extension methods on AsyncSequence) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```swift let packets = bytes.chunks(ofCount: 1024, or: .repeating(every: .seconds(1)), into: Data.self) for try await packet in packets { write(packet) } ``` ### Response #### Success Response (200) An `AsyncChunksOfCountOrSignalSequence` that emits collected chunks. #### Response Example N/A (Emits chunks directly) ``` -------------------------------- ### Create MultiProducerSingleConsumerAsyncChannel Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0016-mutli-producer-single-consumer-channel.md Initializes a new channel and its source with a specified backpressure strategy. The channel and source can be destructured from the returned tuple. ```swift let channelAndSource = MultiProducerSingleConsumerAsyncChannel.makeChannel( of: Int.self, backpressureStrategy: .watermark(low: 2, high: 4) ) // The channel and source can be extracted from the returned type let channel = consume channelAndSource.channel let source = consume channelAndSource.source ``` ```swift let channelAndSource = MultiProducerSingleConsumerAsyncChannel.makeChannel( of: Int.self, backpressureStrategy: .watermark(low: 5, high: 10) ) var channel = consume channelAndSource.channel var source = consume channelAndSource.source ``` -------------------------------- ### Inclusive Reductions Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0015-reductions.md Use these inclusive reductions for scenarios like running tallies where no initial value is provided. They come in throwing and non-throwing flavors. ```swift extension AsyncSequence { public func reductions( _ transform: @Sendable @escaping (Element, Element) async -> Element ) -> AsyncInclusiveReductionsSequence public func reductions( _ transform: @Sendable @escaping (Element, Element) async throws -> Element ) -> AsyncThrowingInclusiveReductionsSequence } ``` ```swift numbers.reductions { $0 + $1 } ``` -------------------------------- ### Using Async Merge with Scoped Lifetime Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncStreaming/NNNN-async-streaming.md Demonstrates how to use the `merge` algorithm with a scoped lifetime approach. This pattern manages concurrent iteration within a structured child task, simplifying cancellation and task management. ```swift await merge(first, second) { merged in for await element in merged { // process element } } ``` -------------------------------- ### Link AsyncAlgorithms Product to Target Source: https://github.com/apple/swift-async-algorithms/blob/main/README.md Include "AsyncAlgorithms" as a dependency for your executable target in Package.swift. ```swift .target(name: "", dependencies: [ .product(name: "AsyncAlgorithms", package: "swift-async-algorithms"), ]), ``` -------------------------------- ### SetAlgebra Initializer Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/AsyncAlgorithms.docc/Guides/Collections.md Enables the creation of SetAlgebra types, such as Set or OptionSet, from an AsyncSequence of elements. ```APIDOC ## SetAlgebra Initializer ### Description Initializes a `SetAlgebra` type (e.g., `Set`, `OptionSet`, `IndexSet`) from an `AsyncSequence` of elements. This initializer is asynchronous and can rethrow errors from the source sequence. ### Method `init(_ source: Source) async rethrows` ### Endpoint N/A (Extension Method) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```swift let set = try await Set(asyncSequenceOfElements) ``` ### Response #### Success Response (200) Initializes the `SetAlgebra` with unique elements from the `AsyncSequence`. #### Response Example ```swift // Example usage: let mySet = try await Set(someAsyncSequence) ``` ``` -------------------------------- ### Zip Iteration Behavior Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0001-zip.md Explains how iteration works for zipped asynchronous sequences, including concurrency, termination, and error handling. ```APIDOC ## Iteration Behavior Each iteration of an `AsyncZipSequence` awaits values from all its base asynchronous sequences concurrently. The iteration completes when a tuple of the latest values is formed. - **Termination**: If any base sequence's iterator returns `nil`, the `AsyncZipSequence` iteration immediately terminates by returning `nil`. All other concurrent iterations are cancelled. - **Error Handling**: If any base sequence's iterator throws an error, all other concurrently running iterations are cancelled, and the thrown error is rethrown, terminating the `AsyncZipSequence` iteration. - **Concurrency Requirements**: For `AsyncZipSequence` to function correctly, its base sequences, elements, and iterators must all be `Sendable`. This ensures that `AsyncZipSequence` itself is `Sendable`. - **Error Propagation**: The `AsyncZipSequence` can throw errors if any of its base sequences can throw. If none of the base sequences can throw, the `AsyncZipSequence` will not throw. ``` -------------------------------- ### Create Additional Source for Multi-Producer Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0016-mutli-producer-single-consumer-channel.md Generate a new source from an existing one to support multiple producers concurrently. ```swift let channelAndSource = MultiProducerSingleConsumerAsyncChannel.makeChannel( of: Int.self, backpressureStrategy: .watermark(low: 2, high: 5) ) var channel = consume channelAndSource.channel var source1 = consume channelAndSource.source var source2 = source1.makeAdditionalSource() group.addTask { try await source1.send(1) } group.addTask() { try await source2.send(2) } print(await channel.next()) // Prints either 1 or 2 depending on which child task runs first print(await channel.next()) // Prints either 1 or 2 depending on which child task runs first ``` -------------------------------- ### Initialize RangeReplaceableCollection from AsyncSequence Source: https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/AsyncAlgorithms.docc/Guides/Collections.md Use this initializer to create any `RangeReplaceableCollection` (like `Array` or `Data`) from an `AsyncSequence`. It is asynchronous and rethrows errors from the source sequence. ```swift extension RangeReplaceableCollection { public init( _ source: Source ) async rethrows where Source.Element == Element } ``` -------------------------------- ### Add Swift Async Algorithms Dependency Source: https://github.com/apple/swift-async-algorithms/blob/main/README.md Add this line to the dependencies in your Package.swift file to include the AsyncAlgorithms library. ```swift .package(url: "https://github.com/apple/swift-async-algorithms", from: "1.0.0"), ``` -------------------------------- ### Usage With FlatMapLatest Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0018-flatMapLatest.md Shows how to use flatMapLatest to process search queries, ensuring only the latest results are displayed by automatically cancelling previous operations. ```swift let searchResults = searchQueries.flatMapLatest { searchAPI($0) } for await result in searchResults { displayResults(result) // Only latest results displayed } ``` -------------------------------- ### MultiProducerSingleConsumerAsyncChannel Methods Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0016-mutli-producer-single-consumer-channel.md This section details the methods available for interacting with the MultiProducerSingleConsumerAsyncChannel, including sending elements and finishing the channel. ```APIDOC ## MultiProducerSingleConsumerAsyncChannel ### Description Represents a channel that allows multiple producers to send elements to a single consumer. ### Methods #### `send(contentsOf sequence: consuming sending S) async throws` ##### Description Sends the elements of a sequence to the channel. ##### Method `mutating func send(contentsOf sequence: consuming sending S) async throws` ##### Parameters - **sequence** (S): The elements to send to the channel. `S` must conform to `Sequence` and its `Element` must be the same as the channel's `Element`. #### `send(_ element: consuming sending Element) async throws` ##### Description Sends a single element to the channel. If a consumer is waiting, it will be resumed. Throws an error if the channel has terminated. ##### Method `mutating func send(_ element: consuming sending Element) async throws` ##### Parameters - **element** (Element): The element to send to the channel. #### `send(contentsOf sequence: consuming sending S) async throws` ##### Description Sends the elements of an asynchronous sequence to the channel. This method returns once the provided asynchronous sequence or the channel finishes. ##### Method `mutating func send(contentsOf sequence: consuming sending S) async throws` ##### Constraints - `Element` must conform to `Sendable`. - `S` must conform to `Sendable` and `AsyncSequence`. - `Element` must be the same as `S.Element`. ##### Parameters - **sequence** (S): The elements to send to the channel. #### `finish(throwing error: Failure? = nil) consuming` ##### Description Indicates that the production of elements has terminated. Subsequent calls to `next()` on the consumer will return `nil` or throw an error. Calling this multiple times has no effect. The channel enters a terminal state and does not accept new elements after this call. ##### Method `consuming func finish(throwing error: Failure? = nil)` ##### Parameters - **error** (Failure?): An optional error to throw upon termination. If `nil`, the channel finishes normally. ``` -------------------------------- ### makeChannel Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0016-mutli-producer-single-consumer-channel.md Factory method to create a new MultiProducerSingleConsumerAsyncChannel and its Source. ```APIDOC ## Static Method: MultiProducerSingleConsumerAsyncChannel.makeChannel ### Description Initializes a new `MultiProducerSingleConsumerAsyncChannel` and an `MultiProducerSingleConsumerAsyncChannel.Source`. This method is used to set up a channel for asynchronous communication. ### Method `static func makeChannel(of elementType: Element.Type = Element.self, throwing failureType: Failure.Type = Never.self, backpressureStrategy: Source.BackpressureStrategy) -> ChannelAndStream` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Returns - **ChannelAndStream** - A tuple containing the channel and its source. The source should be passed to the producer while the channel should be passed to the consumer. ``` -------------------------------- ### next Source: https://github.com/apple/swift-async-algorithms/blob/main/Evolution/0016-mutli-producer-single-consumer-channel.md Asynchronously retrieves the next element from the channel. ```APIDOC ## Method: MultiProducerSingleConsumerAsyncChannel.next ### Description Returns the next element from the channel. If the channel is empty and not finished, this method suspends until an element is available or the channel is closed. Cancellation of the calling task will result in `nil` being returned. ### Method `func next(isolation: isolated (any Actor)? = #isolation) async throws(Failure) -> Element?` ### Parameters #### Path Parameters None #### Query Parameters - **isolation** (isolated (any Actor)?) - Optional isolation context for the operation. #### Request Body None ### Returns - **Element?** - The next buffered element, or `nil` if no further values can be returned or if the task was cancelled. ```