Skip to content

Instantly share code, notes, and snippets.

@Nillerr
Created September 18, 2023 10:39
Show Gist options
  • Save Nillerr/1ae8c0ff7930eb342b2a7f48b15da5d7 to your computer and use it in GitHub Desktop.
Save Nillerr/1ae8c0ff7930eb342b2a7f48b15da5d7 to your computer and use it in GitHub Desktop.
func combineLatest<A, B, R>(_ aSequence: A, _ bSequence: B, transform: @escaping (A.Element, B.Element) -> R) -> AsyncStream<R> where A : AsyncSequence, B : AsyncSequence {
return AsyncStream { (continuation) async in
let aCurrentValue = Ref<A.Element?>(initialValue: nil)
let aTask = Ref<Task<Void, Error>?>(initialValue: nil)
let bCurrentValue = Ref<B.Element?>(initialValue: nil)
let bTask = Ref<Task<Void, Error>?>(initialValue: nil)
aTask.value = Task {
defer { bTask.value?.cancel() }
for try await aValue in aSequence {
aCurrentValue.value = aValue
if let bValue = bCurrentValue.value {
continuation.yield(transform(aValue, bValue))
}
}
}
bTask.value = Task {
defer { aTask.value?.cancel() }
for try await bValue in bSequence {
bCurrentValue.value = bValue
if let aValue = aCurrentValue.value {
continuation.yield(transform(aValue, bValue))
}
}
}
do {
try await aTask.value?.value
try await bTask.value?.value
} catch {
// Nothing
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment