https://kotlinlang.org logo
#coroutines
Title
# coroutines
m

Marc Knaup

10/11/2020, 9:06 PM
Is there a performant way to transform
List<Flow<T>>
into
Flow<List<T>>
where
List<T>
contains the latest value of each
Flow<T>
at the same index.
combine()
is not an option.
I’ve written a simple one, in case someone needs it: https://gist.github.com/fluidsonic/4330ebda9942c57a6660fadba1145362
m

MiSikora

10/12/2020, 8:49 AM
I’m not sure why comine is not an option. I don’t know about performance but I recently had to do this and I used something like this.
Copy code
fun <T> Iterable<Flow<T>>.unwrap(): Flow<List<T>> {
  val emptyFlow = emptyFlow<List<T>>()
  return fold(emptyFlow) { flows, flow ->
    if (flows === emptyFlow) {
      flow.map(::listOf)
    } else {
      flows.combine(flow) { group, item -> group + item }
    }
  }
}
m

Marc Knaup

10/12/2020, 9:36 AM
Because the parallel combine is slow as heck: https://github.com/Kotlin/kotlinx.coroutines/issues/2296
m

MiSikora

10/12/2020, 9:36 AM
Ok, thanks for the link 🙂
b

bezrukov

10/12/2020, 10:37 AM
it's slow because under the hood it uses "fair channels" that calls
yield
each time when element offered with fast path. As far as I understand it's necessary for sequential flows.
when you write
listOf(flow1,flow2,flow3).combine()
you can expect that it will use order of these flows. With your extension you can't expect this. It may lead to the following behavior:
Copy code
time:   | 1 | 2 | 3 | 4 | 5
flow1:  | A |   | B |   | 
flow2:  | w | x | y | z | 
combine:| Aw| Ax| Ay| Az| Bz| <-your extension
stdlib: | Aw| Ax| Bx| By| Bz|
m

Marc Knaup

10/12/2020, 11:47 AM
What would such a time unit be in Kotlin? There is no time frame defined in which values from multiple flows would be merged 🤔 Or is it elements that happen to be collectible in the same “tick”?
Or expressed differently: How is it defined that “B” and “y” arrive at the same time?
b

bezrukov

10/12/2020, 11:49 AM
Or is it elements that happen to be collectible in the same “tick”?
yes, it's just shows that at some time called "3" B and y are ready for collect
m

Marc Knaup

10/12/2020, 11:52 AM
Okay. So if that’s really necessary then it may be better to have two operators, one which is fast and doesn’t care about that, and one that is slow and maintains order if elements arrive “simultaneously”. And clearly document each 🙂
5 Views