Skip to content
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
22 changes: 14 additions & 8 deletions Sources/AsyncAlgorithms/AsyncExclusiveReductionsSequence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,18 @@ extension AsyncSequence {
/// Returns an asynchronous sequence containing the accumulated results of combining the
/// elements of the asynchronous sequence using the given closure.
///
/// This can be seen as applying the reduce function to each element and
/// providing the initial value followed by these results as an asynchronous sequence.
/// Starting from the initial value, this combines each element of the base
/// asynchronous sequence with the running result and emits each intermediate
/// result. The initial value itself is not emitted, so the first element of
/// the returned sequence is the result of combining the initial value with
/// the first element of the base sequence. If the base sequence is empty, the
/// returned sequence is also empty.
///
/// - Parameters:
/// - initial: The value to use as the initial value.
/// - transform: A closure that combines the previously-reduced result and
/// the next element in the receiving asynchronous sequence, which it returns.
/// - Returns: An asynchronous sequence of the initial value followed by the reduced
/// elements.
/// - Returns: An asynchronous sequence of the reduced elements.
@available(AsyncAlgorithms 1.0, *)
@inlinable
public func reductions<Result>(
Expand All @@ -37,16 +40,19 @@ extension AsyncSequence {
/// Returns an asynchronous sequence containing the accumulated results of combining the
/// elements of the asynchronous sequence using the given closure.
///
/// This can be seen as applying the reduce function to each element and
/// providing the initial value followed by these results as an asynchronous sequence.
/// Starting from the initial value, this combines each element of the base
/// asynchronous sequence with the running result and emits each intermediate
/// result. The initial value itself is not emitted, so the first element of
/// the returned sequence is the result of combining the initial value with
/// the first element of the base sequence. If the base sequence is empty, the
/// returned sequence is also empty.
///
/// - Parameters:
/// - initial: The value to use as the initial value.
/// - transform: A closure that combines the previously-reduced result and
/// the next element in the receiving asynchronous sequence, mutating the
/// previous result instead of returning a value.
/// - Returns: An asynchronous sequence of the initial value followed by the reduced
/// elements.
/// - Returns: An asynchronous sequence of the reduced elements.
@available(AsyncAlgorithms 1.0, *)
@inlinable
public func reductions<Result>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,19 @@ extension AsyncSequence {
/// Returns an asynchronous sequence containing the accumulated results of combining the
/// elements of the asynchronous sequence using the given error-throwing closure.
///
/// This can be seen as applying the reduce function to each element and
/// providing the initial value followed by these results as an asynchronous sequence.
/// Starting from the initial value, this combines each element of the base
/// asynchronous sequence with the running result and emits each intermediate
/// result. The initial value itself is not emitted, so the first element of
/// the returned sequence is the result of combining the initial value with
/// the first element of the base sequence. If the base sequence is empty, the
/// returned sequence is also empty.
///
/// - Parameters:
/// - initial: The value to use as the initial value.
/// - transform: A closure that combines the previously reduced result and
/// the next element in the receiving asynchronous sequence and returns
/// the result. If the closure throws an error, the sequence throws.
/// - Returns: An asynchronous sequence of the initial value followed by the reduced
/// elements.
/// - Returns: An asynchronous sequence of the reduced elements.
@available(AsyncAlgorithms 1.0, *)
@inlinable
public func reductions<Result>(
Expand All @@ -38,17 +41,20 @@ extension AsyncSequence {
/// Returns an asynchronous sequence containing the accumulated results of combining the
/// elements of the asynchronous sequence using the given error-throwing closure.
///
/// This can be seen as applying the reduce function to each element and
/// providing the initial value followed by these results as an asynchronous sequence.
/// Starting from the initial value, this combines each element of the base
/// asynchronous sequence with the running result and emits each intermediate
/// result. The initial value itself is not emitted, so the first element of
/// the returned sequence is the result of combining the initial value with
/// the first element of the base sequence. If the base sequence is empty, the
/// returned sequence is also empty.
///
/// - Parameters:
/// - initial: The value to use as the initial value.
/// - transform: A closure that combines the previously reduced result and
/// the next element in the receiving asynchronous sequence, mutating the
/// previous result instead of returning a value. If the closure throws an
/// error, the sequence throws.
/// - Returns: An asynchronous sequence of the initial value followed by the reduced
/// elements.
/// - Returns: An asynchronous sequence of the reduced elements.
@available(AsyncAlgorithms 1.0, *)
@inlinable
public func reductions<Result>(
Expand Down
28 changes: 28 additions & 0 deletions Tests/AsyncAlgorithmsTests/TestReductions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,34 @@ final class TestReductions: XCTestCase {
XCTAssertNil(pastEnd)
}

func test_reductions_empty() async {
let sequence = [Int]().async.reductions("") { partial, value in
partial + "\(value)"
}
var iterator = sequence.makeAsyncIterator()
var collected = [String]()
while let item = await iterator.next() {
collected.append(item)
}
XCTAssertEqual(collected, [])
let pastEnd = await iterator.next()
XCTAssertNil(pastEnd)
}

func test_throwing_reductions_empty() async throws {
let sequence = [Int]().async.reductions("") { (partial, value) throws -> String in
partial + "\(value)"
}
var iterator = sequence.makeAsyncIterator()
var collected = [String]()
while let item = try await iterator.next() {
collected.append(item)
}
XCTAssertEqual(collected, [])
let pastEnd = try await iterator.next()
XCTAssertNil(pastEnd)
}

func test_inclusive_reductions() async {
let sequence = [1, 2, 3, 4].async.reductions { $0 + $1 }
var iterator = sequence.makeAsyncIterator()
Expand Down
Loading