Skip to content

First pass at some documentation for chunked/chunks #92

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 2 commits into from
Mar 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions Sources/AsyncAlgorithms/AsyncChunkedByGroupSequence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,45 @@
//===----------------------------------------------------------------------===//

extension AsyncSequence {
/// Creates an asynchronous sequence that creates chunks of a given `RangeReplaceableCollection`
/// type by testing if elements belong in the same group.
@inlinable
public func chunked<Collected: RangeReplaceableCollection>(into: Collected.Type, by belongInSameGroup: @escaping @Sendable (Element, Element) -> Bool) -> AsyncChunkedByGroupSequence<Self, Collected> where Collected.Element == Element {
AsyncChunkedByGroupSequence(self, grouping: belongInSameGroup)
}

/// Creates an asynchronous sequence that creates chunks by testing if elements belong in the same group.
@inlinable
public func chunked(by belongInSameGroup: @escaping @Sendable (Element, Element) -> Bool) -> AsyncChunkedByGroupSequence<Self, [Element]> {
chunked(into: [Element].self, by: belongInSameGroup)
}
}

/// An `AsyncSequence` that chunks by testing if two elements belong to the same group.
///
/// Group chunks are determined by passing two consecutive elements to a closure which tests
/// whether they are in the same group. When the `AsyncChunkedByGroupSequence` iterator
/// receives the first element from the base sequence, it will immediately be added to a group. When
/// it receives the second item, it tests whether the previous item and the current item belong to the
/// same group. If they are not in the same group, then the iterator emits the first item's group and a
/// new group is created containing the second item. Items declared to be in the same group
/// accumulate until a new group is declared, or the iterator finds the end of the base sequence.
/// When the base sequence terminates, the final group is emitted. If the base sequence throws an
/// error, `AsyncChunkedByGroupSequence` will rethrow that error immediately and discard
/// any current group.
///
/// let chunks = numbers.chunked { $0 <= $1 }
/// for await numberChunk in chunks {
/// print(numberChunk)
/// }
/// // prints
/// // [10, 20, 30]
/// // [10, 40, 40]
/// // [10, 20]
public struct AsyncChunkedByGroupSequence<Base: AsyncSequence, Collected: RangeReplaceableCollection>: AsyncSequence where Collected.Element == Base.Element {
public typealias Element = Collected

/// The iterator for a `AsyncChunkedByGroupSequence` instance.
@frozen
public struct Iterator: AsyncIteratorProtocol {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,24 @@
//===----------------------------------------------------------------------===//

extension AsyncSequence {
/// Creates an asynchronous sequence that creates chunks of a given `RangeReplaceableCollection` type on the uniqueness of a given subject.
@inlinable
public func chunked<Subject : Equatable, Collected: RangeReplaceableCollection>(into: Collected.Type, on projection: @escaping @Sendable (Element) -> Subject) -> AsyncChunkedOnProjectionSequence<Self, Subject, Collected> {
AsyncChunkedOnProjectionSequence(self, projection: projection)
}

/// Creates an asynchronous sequence that creates chunks on the uniqueness of a given subject.
@inlinable
public func chunked<Subject : Equatable>(on projection: @escaping @Sendable (Element) -> Subject) -> AsyncChunkedOnProjectionSequence<Self, Subject, [Element]> {
chunked(into: [Element].self, on: projection)
}
}

/// An `AsyncSequence` that chunks on a subject when it differs from the last element.
public struct AsyncChunkedOnProjectionSequence<Base: AsyncSequence, Subject: Equatable, Collected: RangeReplaceableCollection>: AsyncSequence where Collected.Element == Base.Element {
public typealias Element = (Subject, Collected)

/// The iterator for a `AsyncChunkedOnProjectionSequence` instance.
@frozen
public struct Iterator: AsyncIteratorProtocol {

Expand Down
10 changes: 10 additions & 0 deletions Sources/AsyncAlgorithms/AsyncChunksOfCountOrSignalSequence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,47 +10,57 @@
//===----------------------------------------------------------------------===//

extension AsyncSequence {
/// Creates an asynchronous sequence that creates chunks of a given `RangeReplaceableCollection` type of a given count or when a signal `AsyncSequence` produces an element.
public func chunks<Signal, Collected: RangeReplaceableCollection>(ofCount count: Int, or signal: Signal, into: Collected.Type) -> AsyncChunksOfCountOrSignalSequence<Self, Collected, Signal> where Collected.Element == Element {
AsyncChunksOfCountOrSignalSequence(self, count: count, signal: signal)
}

/// Creates an asynchronous sequence that creates chunks of a given count or when a signal `AsyncSequence` produces an element.
public func chunks<Signal>(ofCount count: Int, or signal: Signal) -> AsyncChunksOfCountOrSignalSequence<Self, [Element], Signal> {
chunks(ofCount: count, or: signal, into: [Element].self)
}

/// Creates an asynchronous sequence that creates chunks of a given `RangeReplaceableCollection` type when a signal `AsyncSequence` produces an element.
public func chunked<Signal, Collected: RangeReplaceableCollection>(by signal: Signal, into: Collected.Type) -> AsyncChunksOfCountOrSignalSequence<Self, Collected, Signal> where Collected.Element == Element {
AsyncChunksOfCountOrSignalSequence(self, count: nil, signal: signal)
}

/// Creates an asynchronous sequence that creates chunks when a signal `AsyncSequence` produces an element.
public func chunked<Signal>(by signal: Signal) -> AsyncChunksOfCountOrSignalSequence<Self, [Element], Signal> {
chunked(by: signal, into: [Element].self)
}

/// Creates an asynchronous sequence that creates chunks of a given `RangeReplaceableCollection` type of a given count or when an `AsyncTimerSequence` fires.
@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *)
public func chunks<C: Clock, Collected: RangeReplaceableCollection>(ofCount count: Int, or timer: AsyncTimerSequence<C>, into: Collected.Type) -> AsyncChunksOfCountOrSignalSequence<Self, Collected, AsyncTimerSequence<C>> where Collected.Element == Element {
AsyncChunksOfCountOrSignalSequence(self, count: count, signal: timer)
}

/// Creates an asynchronous sequence that creates chunks of a given count or when an `AsyncTimerSequence` fires.
@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *)
public func chunks<C: Clock>(ofCount count: Int, or timer: AsyncTimerSequence<C>) -> AsyncChunksOfCountOrSignalSequence<Self, [Element], AsyncTimerSequence<C>> {
chunks(ofCount: count, or: timer, into: [Element].self)
}

/// Creates an asynchronous sequence that creates chunks of a given `RangeReplaceableCollection` type when an `AsyncTimerSequence` fires.
@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *)
public func chunked<C: Clock, Collected: RangeReplaceableCollection>(by timer: AsyncTimerSequence<C>, into: Collected.Type) -> AsyncChunksOfCountOrSignalSequence<Self, Collected, AsyncTimerSequence<C>> where Collected.Element == Element {
AsyncChunksOfCountOrSignalSequence(self, count: nil, signal: timer)
}

/// Creates an asynchronous sequence that creates chunks when an `AsyncTimerSequence` fires.
@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *)
public func chunked<C: Clock>(by timer: AsyncTimerSequence<C>) -> AsyncChunksOfCountOrSignalSequence<Self, [Element], AsyncTimerSequence<C>> {
chunked(by: timer, into: [Element].self)
}
}

/// An `AsyncSequence` that chunks elements into collected `RangeReplaceableCollection` instances by either count or a signal from another `AsyncSequence`.
public struct AsyncChunksOfCountOrSignalSequence<Base: AsyncSequence, Collected: RangeReplaceableCollection, Signal: AsyncSequence>: AsyncSequence, Sendable where Collected.Element == Base.Element, Base: Sendable, Signal: Sendable, Base.AsyncIterator: Sendable, Signal.AsyncIterator: Sendable, Base.Element: Sendable, Signal.Element: Sendable {

public typealias Element = Collected

/// The iterator for a `AsyncChunksOfCountOrSignalSequence` instance.
public struct Iterator: AsyncIteratorProtocol, Sendable {
let count: Int?
var state: Merge2StateMachine<Base, Signal>
Expand Down
4 changes: 4 additions & 0 deletions Sources/AsyncAlgorithms/AsyncChunksOfCountSequence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,24 @@
//===----------------------------------------------------------------------===//

extension AsyncSequence {
/// Creates an asynchronous sequence that creates chunks of a given `RangeReplaceableCollection` of a given count.
@inlinable
public func chunks<Collected: RangeReplaceableCollection>(ofCount count: Int, into: Collected.Type) -> AsyncChunksOfCountSequence<Self, Collected> where Collected.Element == Element {
AsyncChunksOfCountSequence(self, count: count)
}

/// Creates an asynchronous sequence that creates chunks of a given count.
@inlinable
public func chunks(ofCount count: Int) -> AsyncChunksOfCountSequence<Self, [Element]> {
chunks(ofCount: count, into: [Element].self)
}
}

/// An `AsyncSequence` that chunks elements into `RangeReplaceableCollection` instances of at least a given count.
public struct AsyncChunksOfCountSequence<Base: AsyncSequence, Collected: RangeReplaceableCollection>: AsyncSequence where Collected.Element == Base.Element {
public typealias Element = Collected

/// The iterator for a `AsyncChunksOfCountSequence` instance.
@frozen
public struct Iterator: AsyncIteratorProtocol {

Expand Down