Reputation: 13668
My question is it is possible to do something like:
fun <T, R> someFunction(vararg sources<out T>, doSomething: (vararg sources<out T>) -> R) {
// do something here
}
So if I do something like:
someFunction(SomeType<A>(), SomeType<B>(), SomeType<C>()) { a: A, b: B c: C ->
// do Something
}
Basically, the higher ordered function needs to require all the parameter types.
The reason why I'm asking this is that I would like to simplify code that are like this:
inline fun <T1, T2, R> MediatorLiveData<out R>.merge(source1: LiveData<out T1>, source2: LiveData<out T2>, crossinline merger: (T1?, T2?) -> R?) {
addSource(source1) {
this.value = merger.invoke(source1.value, source2.value)
}
addSource(source2) {
this.value = merger.invoke(source1.value, source2.value)
}
}
inline fun <T1, T2, T3, R> MediatorLiveData<out R>.merge(source1: LiveData<out T1>, source2: LiveData<out T2>, source3: LiveData<out T3>, crossinline merger: (T1?, T2?, T3?) -> R?) {
addSource(source1) {
this.value = merger.invoke(source1.value, source2.value, source3.value)
}
addSource(source2) {
this.value = merger.invoke(source1.value, source2.value, source3.value)
}
addSource(source3) {
this.value = merger.invoke(source1.value, source2.value, source3.value)
}
}
inline fun <T1, T2, T3, T4, R> MediatorLiveData<out R>.merge(source1: LiveData<out T1>, source2: LiveData<out T2>, source3: LiveData<out T3>, source4: LiveData<out T4>, crossinline merger: (T1?, T2?, T3?, T4?) -> R?) {
addSource(source1) {
this.value = merger.invoke(source1.value, source2.value, source3.value, source4.value)
}
addSource(source2) {
this.value = merger.invoke(source1.value, source2.value, source3.value, source4.value)
}
addSource(source3) {
this.value = merger.invoke(source1.value, source2.value, source3.value, source4.value)
}
addSource(source4) {
this.value = merger.invoke(source1.value, source2.value, source3.value, source4.value)
}
}
Can anyone suggest something? Thanks in advance!
Upvotes: 0
Views: 244
Reputation: 30645
Try out the following function:
fun <T, R> someFunction(vararg sources: LiveData<out T>, doSomething: (sources: Array<out LiveData<out T>>) -> R) {
// ...
doSomething(sources)
}
It seems we can't use modifier vararg
in lambda expression doSomething
, replacing it with Array
will work.
EDIT: So basically you will be able to do something like the following for different number of sources without creating additional functions like in your example:
fun <T, R> someFunction(vararg sources: LiveData<out T>, doSomething: (sources: Array<out LiveData<out T>>) -> R) {
sources.forEach {
addSource(it) {
doSomething.invoke(sources)
}
}
}
// Call someFunction with different number of args:
val l1: LiveData<Int> = MutableLiveData()
val l2: LiveData<String> = MutableLiveData()
val l3: LiveData<String> = MutableLiveData()
// Call with two args:
someFunction(l1, l2) { sources: Array<out LiveData<out Any>> ->
val data1 = sources[0] as LiveData<Int>
val data2 = sources[1] as LiveData<String>
// do your work here
}
// Or Call with three args:
someFunction(l1, l2, l3) { sources: Array<out LiveData<out Any>> ->
val data1 = sources[0] as LiveData<Int>
val data2 = sources[1] as LiveData<String>
val data3 = sources[2] as LiveData<String>
// do your work here
}
Upvotes: 1