Skip to content
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

add any operator #2239

Closed
helmbold opened this issue Sep 10, 2020 · 7 comments
Closed

add any operator #2239

helmbold opened this issue Sep 10, 2020 · 7 comments

Comments

@helmbold
Copy link

To make Kotlin Flow more suitable for a wide range of tasks, I suggest to add an any function like in Reactor.

Description

Emit a single boolean true if any of the values of this Flux sequence match the predicate.

Signature

fun <T> Flow<T>.any(predicate: (T) -> Boolean)): Flow<Boolean>
@elizarov
Copy link
Contributor

You can use first { ... } terminal operator with Kotln Flow. I am not sure why would you need any. Can you give an example?

@helmbold
Copy link
Author

helmbold commented Sep 10, 2020

Agreed. Since Flow doesn't have the concept of Mono and would terminate after emitting the first (and only) element adding any wouldn't make a big difference.

I just want to suggest the development of some more operators, since I was missing some operators I know from Reactor recently. So my approach is to go the the list of Flux operators, check if they already exist in Flow or were already filed as an issue, and then create a new issue. But maybe I generate too much duplicates (due slightly different naming) or operators that could easily replaced with existing Flow functions. @elizarov: I don't want to bother you, so if you don't think my approach is helpful, let me know.

@JakeWharton
Copy link
Contributor

Since Flow doesn't have the concept of Mono

A Mono in coroutines is just a suspend fun, an asynchronous function invocation that can only produce a value or exception.

@elizarov
Copy link
Contributor

This approach is not helpful. We don't have a goal of having all the Reactor operators. Our goals are completely opposite. We want to have a small core set of operators that people can easily learn and use to write their code. So, we are adding operators only when there are strong supporting use-cases to have them.

@helmbold
Copy link
Author

Ok, thanks for clarification.

@jfsanchez91
Copy link

jfsanchez91 commented Jul 26, 2022

You can implement your own extension functions:

import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.count
import kotlinx.coroutines.flow.firstOrNull

suspend fun <T> Flow<T>.all(predicate: suspend (T) -> Boolean): Boolean {
    return this.count { !predicate(it) } == 0
}

suspend fun <T> Flow<T>.any(predicate: suspend (T) -> Boolean): Boolean {
    return this.firstOrNull { predicate(it) } != null
}

Testing

@Test
fun `Flow.all checks all elements match the predicate`() = runTest {
    val items = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 0).asFlow()
    Assertions.assertTrue(items.all { it <= 10 })
    Assertions.assertFalse(items.all { it >= 4 })
}

@Test
fun `Flow.any checks that at least one element matches the predicate`() = runTest {
    val items = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 0).asFlow()
    Assertions.assertTrue(items.any { it <= 0 }) // '0' matches
    Assertions.assertTrue(items.any { it >= 4 }) // '4, 5, 6, 7, 8, 9' match
    Assertions.assertFalse(items.any { it < 0 }) // No matches
}

@jdreddaway
Copy link

jfsanchez91 it would be better performance to use this.firstOrNull() and check for null instead of try/catching.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants