How would I `combine()` 7 flows? Use array & s...
# coroutines
r
How would I
combine()
7 flows? Use array & smartcast?
s
I think you mean just cast like
something as T
And yes, this is what out of the box
combine
does anyway
Copy code
public fun <T1, T2, T3, T4, T5, R> combine(
    flow: Flow<T1>,
    flow2: Flow<T2>,
    flow3: Flow<T3>,
    flow4: Flow<T4>,
    flow5: Flow<T5>,
    transform: suspend (T1, T2, T3, T4, T5) -> R
): Flow<R> = combineUnsafe(flow, flow2, flow3, flow4, flow5) { args: Array<*> ->
    transform(
        args[0] as T1,
        args[1] as T2,
        args[2] as T3,
        args[3] as T4,
        args[4] as T5
    )
}
r
Yeah, but I can't write my own with > 5 elements without manually adjusting elements
s
Yes, that’s the way
Copy code
fun <T1, T2, T3, T4, T5, T6, T7, R> combine(
    flow: Flow<T1>,
    flow2: Flow<T2>,
    flow3: Flow<T3>,
    flow4: Flow<T4>,
    flow5: Flow<T5>,
    flow6: Flow<T6>,
    flow7: Flow<T7>,
    crossinline transform: suspend (T1, T2, T3, T4, T5, T6, T7) -> R
): Flow<R> {
    return kotlinx.coroutines.flow.combine(flow, flow2, flow3, flow4, flow5, flow6, flow7) { args: Array<*> ->
        @Suppress("UNCHECKED_CAST")
        transform(
            args[0] as T1,
            args[1] as T2,
            args[2] as T3,
            args[3] as T4,
            args[4] as T5,
            args[5] as T6,
            args[6] as T7,
        )
    }
}
Or perhaps I don’t quite get what you mean by “adjusting elements manually”
r
Copy code
fun <A,B,C,D,E,F,Z> combine(
    aF: Flow<A>,
    bF: Flow<B>,
    cF: Flow<C>,
    dF: Flow<D>,
    eF: Flow<E>,
    fF: Flow<F>,
    function: Function6<A, B, C, D, E, F, Z>
): Flow<Z> {
    val combined =
        kotlinx.coroutines.flow.combine(aF, bF, cF, dF, eF) { a, b, c, d, e  ->
            Tuple5(a, b, c, d, e)
        }
    return kotlinx.coroutines.flow.combine(combined, fF) { comb, f ->
        function(comb.first, comb.second, comb.third, comb.fourth, comb.fifth, f)
    }
}
s
Sure, that’d do too 👌
However I see no benefits in wrapping it with Tuple5
r
Ah, use a builtin tuple instead?
s
No, I mean just pass it to your
transform
function, I think it should be possible
r
Not sure if it'll work correctly if it's not passed through the second combine
s
Copy code
fun <A, B, C, D, E, F, Z> combine(
    aF: Flow<A>,
    bF: Flow<B>,
    cF: Flow<C>,
    dF: Flow<D>,
    eF: Flow<E>,
    fF: Flow<F>,
    function: Function6<A, B, C, D, E, F, Z>
): Flow<Z> {
    return combine(aF, bF, cF, dF, eF, fF) { a, b, c, d, e, f ->
        function(a, b, c, d, e, f)
    }
}
r
That looks... recursive?
s
Oopsie 😄
Copy code
fun <A, B, C, D, E, F, Z> combine(
    aF: Flow<A>,
    bF: Flow<B>,
    cF: Flow<C>,
    dF: Flow<D>,
    eF: Flow<E>,
    fF: Flow<F>,
    function: Function6<A, B, C, D, E, F, Z>
): Flow<Z> {
    return combine(aF, bF, cF, dF, eF, fF) { arr ->
        @Suppress("UNCHECKED_CAST")
        function(
            arr[0] as A, 
            arr[1] as B, 
            arr[2] as C, 
            arr[3] as D, 
            arr[4] as E, 
            arr[5] as F
        )
    }
}
r
Yeah, that looks neater
j
You probably won’t run into this in practice, but I ran into a limit using this pattern of combining flows. For what ever reason any more than 20 combined flow failed. I don’t have the stack-trace I got but I remember the errors we very unhelpful.
😱 1