-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Introduce Flow.any, Flow.all, Flow.none #4249
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
Conversation
I took inspiration from other tests, which seem to use |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
expect
and finish
are used to describe when exactly which code is run. If there are 100 steps, the chain of calls must be expect(1)
, expect(2)
, expect(3)
... finish(100)
and nothing else. If the test is broken and expect(5)
runs before expect(4)
did, the test fails.
This isn't useful for the tests you've already written. It could potentially be useful for tests that are missing, those that show short-circuiting behavior: flow { emit(1); fail("unreached") }.any { it == 1 }
should finish without an error. Or maybe not.
* This operation is *terminal*. | ||
* | ||
* @see Iterable.any | ||
* @see Sequence.any |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Flow.all
also seems relevant.
@@ -164,3 +164,46 @@ public fun <T> Flow<T>.chunked(size: Int): Flow<List<T>> { | |||
result?.let { emit(it) } | |||
} | |||
} | |||
|
|||
/** | |||
* Returns `true` if at least one element matches the given [predicate]. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another important property is that it immediately stops collecting the flow. See https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/first.html
Also, this only returns false
if the flow completes without emitting a value that matches the predicate. I'm not sure if it's worth spelling out (this does seem obvious).
Finally, please include a simple usage sample in the documentation for every new function.
*/ | ||
@ExperimentalCoroutinesApi | ||
public suspend fun <T> Flow<T>.all(predicate: suspend (T) -> Boolean): Boolean = | ||
count { !predicate(it) } == 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This implementation will hang in this scenario: flow { while (true) { emit(5) } }.all { it == 4 }
.
*/ | ||
@ExperimentalCoroutinesApi | ||
public suspend fun <T> Flow<T>.none(predicate: suspend (T) -> Boolean): Boolean = | ||
count { predicate(it) } == 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Likewise, it will hang for flow { while (true) { emit(5) } }.none { it == 5 }
. Please include these scenarios (and a similar one for any
) as tests.
@CLOVIS-AI would you like to continue this PR or should we handle it from here? |
I would love to, but sadly my schedule doesn't allow me too… Feel free to make the changes you want if I'm too slow :) |
Closed in favor of #4304 |
As discussed in #4212.
This is my first proper contribution to Coroutines, so please be nice :)
At this stage, my goals are:
• Optimal API surface
• Correctness
I have not made any attempts to improve performance. In particular, I wouldn't be surprised if
any
could be improved. I believeall
andnone
are optimal.