Kotlin / kotlinx.coroutines

Library support for Kotlin coroutines
Apache License 2.0
13.05k stars 1.85k forks source link

Add any, all, none operators #2664

Open chachako opened 3 years ago

chachako commented 3 years ago

This can make the collect result more concise, just like list.any {it.is..}

elizarov commented 3 years ago

Why would you need it with Flow? What kind of code do you write that needs it?

chachako commented 3 years ago

Why would you need it with Flow? What kind of code do you write that needs it?

In the data return of Android-DataStore, sometimes I need to ensure that the data contains the data I want, then should I use any { true }? In addition, I used a Flow to construct a folder, I also need to use any to determine whether there is a matches file in it

elizarov commented 3 years ago

Having determined if it contains the data you need, what are you doing next? Do you run the source flow again to actually extract the data or what? Can you give an example snipped of code in which you envision that any is going to be useful?

dkhalanskyjb commented 3 years ago

(This is a side note, not a resolution of any kind) It looks like these operations are simple enough to introduce them in place:

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

public suspend fun <T> Flow<T>.all(predicate: suspend (T) -> Boolean): Boolean =
    dropWhile { predicate(it) }.firstOrNull() == null

public suspend fun <T> Flow<T>.none(predicate: suspend (T) -> Boolean): Boolean =
    all { !predicate(it) }

Such implementations can be easily modified to instead output the example (or the counter-example) of the matching element, one just has to remove the comparisons with null.

fvasco commented 3 years ago

(This is a side note, not a resolution of any kind) It looks like these operations are simple enough to introduce them in place:

Not so simple...

    println(flowOf(null).any  { it == null }) // false
    println(flowOf(null).all  { it != null }) // true
    println(flowOf(null).none { it == null }) // true
jablko commented 3 years ago

I'd be grateful for adding Flow<Boolean>.all() and Flow<Boolean>.any() to the library (none() is just !any()).

I use the following shortcuts in my project, but it'd be nice if they came included:

suspend fun Flow<Boolean>.all() = firstOrNull { !it } == null
suspend fun Flow<Boolean>.any() = firstOrNull { it } != null

They're useful for getting the conjunction/disjunction of deferreds, with short-circuiting, e.g.:

listOf(a, b).map { it::await.asFlow() }.merge().all()

vs.


a.await() && b.await() // Infinitely slower, if b completes false while a never completes