Is there a way to poll a single element from Flow,...
# coroutines
t
Is there a way to poll a single element from Flow, like Channel.receive ()? I want to poll the data inside a recursive parser function instead of always receiving the data in the same lambda.
g
No, there is no way, Flow is cold stream, and even hot version of it doesn’t work like that
What is your use case?
Channel may be right abstraction if this what you need
t
Copy code
// parser with recursive call
suspend fun simpleParser(ch: ReceiveChannel<Char>, nest: Int = 0) {
   while (true) {
      when (val a = ch.receiveOrNull()) {
         null, ']' -> break
         '[' -> simpleParser(ch, nest + 1)
         else -> println("$nest $a")
      }
   }
}

runBlocking {
   simpleParser(
      flowOf('a', '[', 'b', ']', 'c')
         .produceIn(this)
   )
}
I want to do the same thing with keeping the cold stream
maybe I want Flow.iterator()
it create reading context similar to collect(), but also provide reader object. like
flow.collectIterator{ it -> while(it.hasNext() ) it.read() }
g
There is no such thing as hasNext() in Flow, that the whole point of cold streams, they are push based, not pull based
I don't see why in example above you need while (true), why not simple collect? Maybe there is some more wider context, because now I don't see what converting to channel gives here. Just throw cancellation exception instead of break to stop collecting
You also can use takeUntil operator to stop collecting
t
In the above example, when the parentheses appear, it make a nested recursive call and read the continuation of the flow. but in case of your "stop collecting", how can I write the such control ?