Is there an API like `transform` that gives you fu...
# general-advice
f
Is there an API like
transform
that gives you functions for both receiving and for emitting, instead of being automatically called once per published item with the value being passed into the lambda? Sort of like how a channel has a suspending
receive
function
e
you could write
Copy code
fun <T, R> Flow<T>.transform(block: (from: ReceiveChannel<T>, to: SendChannel<R>) -> Unit): Flow<R> = channelFlow {
    coroutineScope {
        block(this@transform.produceIn(this@coroutineScope), this@channelFlow)
    }
}
f
Oh, I didn't know about produceIn, that's a good one
You could even do this and put send and receive in the same scope, instead of splitting the scopes into two parameters:
Copy code
inline fun <T, R> Flow<T>.channelTransform(crossinline block: suspend ChannelTransformScope<T, R>.() -> Unit): Flow<R> = channelFlow {
    coroutineScope {
        val recv = this@channelTransform.produceIn(this@coroutineScope)
        val send = this@channelFlow
        ChannelTransformScopeImpl(recv, send).block()
    }
}

interface ChannelTransformScope<out T, in R> : ReceiveChannel<T>, SendChannel<R>
@PublishedApi
internal class ChannelTransformScopeImpl<out T, in R>(val rec: ReceiveChannel<T>, val send: SendChannel<R>) :
    ReceiveChannel<T> by rec, SendChannel<R> by send, ChannelTransformScope<T, R>
e
or use context parameters :)
f
Wouldn't the context parameters only let you call the lambda in
channelTransform
implicitly in a scope where the context parameters are provided, but they still need to be named in the lambda in the actual usage?
e
yes, but it's just a
with
away
although so is the explicit parameter version so I guess that's a wash
👍 1
f
Each with adds an indentation level to the usage though
I'm not a fan
f
That's cursed lmao