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

Flow<*>.filterIsInstance is missing its Class<R> overload #3240

Closed
dmstocking opened this issue Apr 7, 2022 · 7 comments
Closed

Flow<*>.filterIsInstance is missing its Class<R> overload #3240

dmstocking opened this issue Apr 7, 2022 · 7 comments
Assignees
Labels

Comments

@dmstocking
Copy link

The Kotlin stdlib provides filterIsInstance for Array and Iterable with an inline and non inline version (aka with Class). Flow does not include the Class version. This seems inconsistent and that Flow should add a variant that takes the Class. I have encountered this myself and ended up writing my own filterIsInstance to do just that.

@Suppress("UNCHECKED_CAST")
public fun <R> Flow<*>.filterIsInstance(klass: Class<R>): Flow<R> = filter { klass.isInstance(it) } as Flow<R>
@dmstocking dmstocking changed the title Flow<*>.filterIsInstance is missing its Class variant Flow<*>.filterIsInstance is missing its Class<R> variant Apr 7, 2022
@dmstocking dmstocking changed the title Flow<*>.filterIsInstance is missing its Class<R> variant Flow<*>.filterIsInstance is missing its Class<R> overload Apr 7, 2022
@qwwdfsad qwwdfsad added the flow label Apr 11, 2022
@qwwdfsad
Copy link
Contributor

This is indeed a pretty simple extension. Could you please elaborate on whether you have an actual use-case for Class-based filtering or just would like to see the API aligned with Collection API?

Could you please elaborate on your use-case?

@dmstocking
Copy link
Author

I would like it fixed for both real life use cases and consistency. I mostly implement protocols for communication applications (like XMPP). What ends up happening is that there are a lot of features that only listen to one type of message. So I usually end up writing a helper function to only get the message you want. It also ends up being more type safe, because I specify the inheritance of the generic parameter. If you just use filterIsInstance, you don't end up getting any type safety really due to the compiler just walking up the tree until it finds Any. Anyway if you just have the inline version, it becomes very hard to make a useful function without also exposing private variables.

    private val messages = MutableSharedFlow<Message>()

// with this new function I can do
    fun <T : Message> messages(clazz: Class<T>): Flow<T> = messages.filterIsInstance(clazz)
    inline fun <reified T : Message> messages(): Flow<T> = messages(T::class.java)

// without I have to expose a function I don't really want
    private fun messagesRaw(): Flow<Message> = messages
    inline fun <reified T : Message> messages(): Flow<T> = messagesRaw().filterIsInstance(clazz)

@IgnatBeresnev
Copy link
Member

Implemented in #3464

@dkhalanskyjb
Copy link
Collaborator

Our workflow is different: a bot closes the issues automatically once the fixes are part of a release.

@dkhalanskyjb dkhalanskyjb reopened this Sep 28, 2022
@IgnatBeresnev
Copy link
Member

a bot closes the issues automatically once the fixes are part of a release

Some sort of wizardry! Sorry 😅

@qwwdfsad
Copy link
Contributor

qwwdfsad commented Sep 28, 2022

Yeah, it's kinda bummer from the maintenance perspective, but it is more transparent for users -- our master reflects the latest release, and open issues are one definitely not released yet

@dmstocking
Copy link
Author

Hurray!

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

No branches or pull requests

4 participants