-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Flow.transformWhile operator #2065
Labels
Comments
elizarov
added a commit
that referenced
this issue
May 27, 2020
Also, all flow-truncating operators are refactored via a common internal collectWhile operator that properly uses AbortFlowException and checks for its ownership, so that we don't have to look for bugs in interactions between all those operators (and zip, too, which is also flow-truncating). Fixes #2065
elizarov
added a commit
that referenced
this issue
Jun 22, 2020
Also, all flow-truncating operators are refactored via a common internal collectWhile operator that properly uses AbortFlowException and checks for its ownership, so that we don't have to look for bugs in interactions between all those operators (and zip, too, which is also flow-truncating). Fixes #2065
recheej
pushed a commit
to recheej/kotlinx.coroutines
that referenced
this issue
Dec 28, 2020
Also, most flow-truncating operators are refactored via a common internal collectWhile operator that properly uses AbortFlowException and checks for its ownership, so that we don't have to look for bugs in interactions between all those operators (and zip, too, which is also flow-truncating). But `take` operator still users a custom highly-tuned implementation. Fixes Kotlin#2065 Co-authored-by: EdwarDDay <4127904+EdwarDDay@users.noreply.github.com> Co-authored-by: Louis CAD <louis.cognault@gmail.com>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Kotlin flow provides
Flow<T>.takeWhile { ... }
operator that emits values while the predicate returnstrue
and then completes the flow without emitting the last value (where the predicate returned true). Its behavior, in this respect, is consistent withdropWhile
operator.In light of the design of shared flows (see #2034) that never complete by themselves there is a use-case where the matching value needs to be emitted, too. For example, consider a shared flow of download progress messages that ends with a message that download was done. We want to use this shared flow in a way that it completes when the download is done but also emits this last value because it also contains additional information. See also the similar request in #1816 (comment)
Naming challenges
Both RxJava and Project Reactor provide
takeUntil
operators for this use-case so that you can writetakeUntil { it.isTheLastOne() }
. However, the word "Until" has a completely different meaning in Koltin's core libraries. It is used to indicate a range up to, but excluding the last element. Moreover, Kotlin (the language) does not have any kind ofrepeat ... until predicate
loop that can serve as inspiration. Kotlin consistently useswhile
for that purpose in both pre-conditionwhile(predicate) { ... }
and post-conditiondo { ... } while(predicate)
forms. SotakeUntil
name is a no-go for Kotlin.RxJS provides
takeWhile(predicate, inclusive = true)
operator for this use-case. However, we feel that accepting boolean here provides misplaced flexibility, since in all the uses it is likely going to be just constant and dedicated version oftakeWhile
operator would have worked better.We cannot find a Kotliny name for this kind of use-case-specific operator.
Flow-style flexiblity
Flow-truncation operators (like
takeWhile
) are quite difficult to write correctly, so it would be wrong to leave the use-case of truncating a flow and emitting the last element to be unmet. However, we do have a similar problem in other places of Kotlin Flow design where some operators (likemapLatest
) are too inflexible for some specific use-cass. We are aiming to minimize the number of operators in the library, and we want to provide both a flexible and easy-to-use operator. Hence we havetransformXxx
operators (liketransformLatest
) that accept a block of code that can make a decision of what and when to emit.So, the proposal is to take the same road here and provide
transformWhile
operator:The
transformWhile
operator generalizestakeWhile
just liketransform
operator generalizes bothfilter
/map
andtransformLatest
generalizesmapLatest
:Using this
transformWhile
operator one can complete a flow on the last value and emit it, too, by writing:The text was updated successfully, but these errors were encountered: