Skip to content

Instantly share code, notes, and snippets.

@chriseidhof
Last active December 6, 2021 05:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chriseidhof/2518257b4df3402990c7b3361181f18b to your computer and use it in GitHub Desktop.
Save chriseidhof/2518257b4df3402990c7b3361181f18b to your computer and use it in GitHub Desktop.
AsyncZipped
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