groostav
07/03/2019, 6:46 PMSequence that work for suspend contexts? IE i have a sequence and I want to map on it in a suspend callerbloder
07/03/2019, 7:08 PMFlow comes to supply this need, no?groostav
07/03/2019, 7:57 PMmap calls to happen lazily instead of eagerlygroostav
07/03/2019, 7:57 PMbdawg.io
07/03/2019, 8:28 PMmap operations on a Sequence will still happen lazily. They just will be blocking on each element that's transformed.bloder
07/03/2019, 9:37 PMbloder
07/03/2019, 9:38 PMclass ConcurrentSequence<T>(val sequence: Sequence<T>) : CoroutineScope by CoroutineScope(Dispatchers.Unconfined)
suspend fun <T, R> ConcurrentSequence<T>.map(transform: (T) -> R): ConcurrentSequence<R> = withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
ConcurrentSequence(sequence.map(transform))
}
suspend fun <T> ConcurrentSequence<T>.first(): T = sequence.first()
fun <T> concurrentSequenceOf(vararg elements: T): ConcurrentSequence<T> = ConcurrentSequence(elements.asSequence())bloder
07/03/2019, 9:42 PMbdawg.io
07/03/2019, 10:21 PMwithContext(<http://Dispatchers.IO|Dispatchers.IO>) block returns immediately though. There's no reason to have the map function itself suspend. It's an intermediate and a stateless function that doesn't cause the sequence to be evaluatedbdawg.io
07/03/2019, 10:24 PMbloder
07/03/2019, 10:28 PMbdawg.io
07/03/2019, 10:30 PMtoList or iterating over the sequence) needs to be suspending. Sequence piggy-backs off of the JVM Iterator which doesn't support suspend, making it blocking to iterate over the sequence using the iterator. Since a sequence operator directly uses the Iterator provided by the previous Sequence in the chain, you'll only have blocking evaluation of sequences. For example, sequence.filter { ... }.map { ... }, the map operator uses the Iterator of elements provided by the filter operator. As such, even writing a different map extension function that accepts a suspending transform method will still be blocking because of the iterator from filterbdawg.io
07/03/2019, 10:32 PMFlow is a completely separate API from Sequence, because to have concurrent evaluation, you have to no longer depend on the core mechanism that sequences were built on (JVM iterators that are only blocking)bloder
07/03/2019, 10:52 PMbdawg.io
07/04/2019, 1:11 PMSequence<Deferred<T>> and then do a terminal operator that fires of all of the coroutines and then perform an await.
coroutineScope {
sequence.map { value ->
async { doSomethingSuspend(value) }
}.toList().awaitAll()
}
It wouldn't fit the "potentially infinite" aspect of sequences.