Skip to content

Introduce Flow.all/any/none operators #4212

Closed
@CLOVIS-AI

Description

@CLOVIS-AI

Use case

I have a complex Flow that possesses many elements. I have a business rule that is, literally, to do something if any of them satisfies a condition.

If I were using List or Set, I would use any { theCondition(it) }. However, Flow doesn't seem to have any.

There is an old issue (#2239) that asks for this feature, and is closed because of alternative implementations:

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

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

I dislike this solution because:

  • The first one doesn't work with a Flow<Foo?> because firstOrNull is only available on non-nullable types.
  • Both options obfuscate the operation I am actually attempting to perform.

I believe it is worth having any/all/none directly in the library because the proposed implementation have downsides.

The Shape of the API

suspend fun <T> Flow<T>.any(predicate: suspend (T) -> Boolean): Boolean
suspend fun <T> Flow<T>.all(predicate: suspend (T) -> Boolean): Boolean
suspend fun <T> Flow<T>.none(predicate: suspend (T) -> Boolean): Boolean

Prior Art

These three functions are already available on Iterable and Sequence. The behavior should be the same.

all and none can use the count operator under the hood, since it already shortcuts. I believe this is a possible implementation of any, though I haven't tested it yet:

suspend fun <T> Flow<T>.any(predicate: suspend (T) -> Boolean) = this
    .transformWhile {
        if (predicate(it)) {
            emit(true)
            false // ONE element MATCHES, no need to go further
        } else {
            true // continue
        }
    }
    .onEmpty { emit(false) }
    .first()

I can submit a PR if you think this is worth pursuing.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions