https://kotlinlang.org logo
#coroutines
Title
# coroutines
f

florent

07/16/2021, 9:12 PM
Hi, I got an issue with that code:
Copy code
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.receiveAsFlow
import org.junit.Test

class ExampleUnitTest {

    @Test
    fun `kotlin language error maybe`() {
        val channel = Channel<String>()

        channel.receiveAsFlow()
            .map { State.Content(it) as State }
            .catch { emit(State.Error) }
            .onStart { emit(State.Loading) }
    }

    sealed class State {
        object Loading : State()
        object Error : State()
        data class Content(val content: String) : State()
    }
}
If I keep the
as State
the compiler mark is as unnecessary, if I remove it the code doesn't compile. Is there an alternative way to write this so it compiles? I have tried using the <> syntax but it doesn't seems to work
f

Francesc

07/16/2021, 11:14 PM
You are maping to
State.Content
so the compiler infers that your flow is of type
State.Content
, not
State
. You have to be explicit, change it like so
Copy code
fun `kotlin language error maybe`() {
            val channel = Channel<String>()
            channel.receiveAsFlow()
                .map<String, State> { State.Content(it) }
                .catch { emit(State.Error) }
                .onStart { emit(State.Loading) }
        }
f

florent

07/16/2021, 11:24 PM
perfect thanks!
👍 1
e

ephemient

07/17/2021, 7:33 AM
you can also use the fact that
Flow<out T>
is covariant, and instead write
Copy code
channel.receiveAsFlow()
    .map { State.Content(it) }
    .catch<State> { emit(State.Error) }
    .onStart { emit(State.Loading) }
because
Flow<State.Content>
is a
Flow<State>
there's similar tricks like
Copy code
channel.receiveAsFlow()
    .map { State.Content(it) }
    .onEach<State> {}
    .catch { emit(State.Error) }
    .onStart { emit(State.Loading) }
but all of this is effectively the same, just influencing Kotlin's type inference
(the equivalent in Rust would only require `.map<_, State>`… but Kotlin forces you to write every type parameter if you write any one of them)
4 Views