Last active
December 6, 2021 05:29
-
-
Save chriseidhof/2518257b4df3402990c7b3361181f18b to your computer and use it in GitHub Desktop.
AsyncZipped
This file contains 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
struct AsyncZippedSequence<L, R>: AsyncSequence where L: AsyncSequence, R: AsyncSequence { | |
typealias Element = (L.Element, R.Element) | |
var l: L | |
var r: R | |
func makeAsyncIterator() -> AsyncZippedIterator<L.Element, R.Element> { | |
AsyncZippedIterator(l, r) | |
} | |
} | |
actor AsyncZippedIterator<L, R>: AsyncIteratorProtocol { | |
var left: () async throws -> L? | |
var right: () async throws -> R? | |
var done = false | |
init<S0: AsyncSequence, S1: AsyncSequence>(_ l: S0, _ r: S1) where S0.Element == L, S1.Element == R { | |
var it0 = l.makeAsyncIterator() | |
var it1 = r.makeAsyncIterator() | |
left = { try await it0.next() } | |
right = { try await it1.next() } | |
} | |
func next() async throws -> (L, R)? { | |
guard !done else { return nil } | |
async let l = left() | |
async let r = right() | |
let (x,y) = try await (l, r) | |
guard let x0 = x, let y0 = y else { | |
done = true | |
return nil | |
} | |
return (x0, y0) | |
} | |
} | |
func counter(range: Range<Int>) -> AsyncStream<Int> { | |
AsyncStream<Int> { continuation in | |
for i in range { | |
continuation.yield(i) | |
} | |
} | |
} | |
extension AsyncSequence { | |
func zip<R: AsyncSequence>(_ other: R) -> AsyncZippedSequence<Self, R> { | |
AsyncZippedSequence(l: self, r: other) | |
} | |
} | |
func sample() async throws { | |
let x = counter(range: 0..<100) | |
let y = counter(range: 30..<40) | |
let test = x.zip(y) | |
for try await pair in test { | |
print(pair) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment