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

julian

07/02/2020, 1:46 AM
Is there a way to terminate a flow from within an intermediate operator lambda? For example, a flow emits 5 random numbers between 1-10. Inside
map
, if the number is over 5, you terminate the flow.
👆 1
o

octylFractal

07/02/2020, 1:47 AM
cancel()
?
i.e. just cancel whatever job is in the coroutine context
j

julian

07/02/2020, 1:49 AM
I tried cancel, but it looks like that operator isn't available on the receiver within an intermediate flow operator.
Would there be a way to cancel the flow without canceling the context's job?
o

octylFractal

07/02/2020, 1:51 AM
they're the same thing afaik
you can't do
coroutineContext.cancel()
?
a

Adam Powell

07/02/2020, 2:01 AM
Or just
throw CancellationException()
👍🏾 1
j

julian

07/02/2020, 2:01 AM
Yup, that worked. Thanks @octylFractal. However, something a bit weird happens. For example:
Copy code
val pf = flowOf(1,2,3).map { if (it == 3) coroutineContext.cancel() else it }
runBlocking {
    val l = pf.toList()
    println(l)
}
prints:
Copy code
[1, 2, kotlin.Unit]
It's that last item
kotlin.Unit
that's surprising.
o

octylFractal

07/02/2020, 2:02 AM
nothing returns
void
in kotlin, it always returns
Unit
, so you're returning
Unit
from
cancel()
there
in this case yes, perhaps throwing the
CancellationException
would be better
j

julian

07/02/2020, 2:03 AM
K. I'll try that. Thanks!
So throwing
CancellationException
works, but
catch
must also be used to be able to get the items emitted before the exception is thrown. Otherwise partial collection doesn't occur.
Thanks @octylFractal @Adam Powell!
z

Zach Klippenstein (he/him) [MOD]

07/02/2020, 2:18 AM
There's actually a PR open to introduce an operator that is for exactly this use case I think: https://github.com/Kotlin/kotlinx.coroutines/pull/2066
1
j

julian

07/02/2020, 2:23 AM
Nice! Thanks @Zach Klippenstein (he/him) [MOD]! Maybe it'll be available soon.
l

louiscad

07/02/2020, 5:52 AM
Throwing a
CancellationException
is not the right way as it's ambiguous with other cancellation causes. You can take a look at how the
take
intermediate operator is done, and that can help to do what you want. Or you can copy
transformWhile
that Zach linked, or wait for it to be merged (which might take a while).
👍 1
t

tseisel

07/03/2020, 7:37 PM
How about
takeWhile
?
2 Views