I have asked the question based on this topic Base Question
So, i want to ask in advanced. With someone answered the question with Array and List
Class Test<T,V>{
var functionPara :(()->T)? = null
var recallFunctionWithFunction:( (Array<out T>) -> V)? = null
constructor(value: ()->T, recallFunctionWithFunction: (Array<out T>) -> V ){
this.functionPara = value
this.recallFunctionWithFunction = recallFunctionWithFunction
}
inline fun <reified T, V> compose(crossinline f: (Array<out T>) -> V, vararg g: () -> T): () -> V {
val results = g.map { it() }
return { f(results.toTypedArray()) }
}
fun <T, V> compose(f: (List<out T>) -> V, vararg g: () -> T): () -> V {
val results = g.map { it() }
return { f(results) }
}
}
fun runCompose(){
compose(functionPara,recallFunctionWithFunction).invoke()
}
But i discovered that When i reference a function with vararg parameter like that
fun functionA(vararg :Observable<Any>):LiveData<Boolean>{
}
fun functionB():Observable<Any>{
}
When i do something like ::functionA the type of A will be Array<out Observable<Any>>->LiveData<Boolean>
Therefore , when i do something like that
Test<Observable<Any>,LiveData<Boolean>>(::functionB,::functionA).runCompose()
Situation 1 If I use the compose function with accepting List type it will show type mismatch due to referencing ::functionA will return Array
Situation 2 If i use the compose function with accepting Array type it will show the error
Cannot use 'T' as reified type parameter. Use a class instead
In previous post , some answered me that convert the array to list. But how to convert reference function with vararg parameter with Originally Array<out to List <out
??
when i reference a function like ::function the type must be Array<out
but i want to plug it into compose function. I must convert it.
Can anyone help? i stuck in there long days. Hope someone can save me!!
You can't convert a list to a typed array because of types erasure. I think the easiest way is to use List
everywhere.
class Test<T, V>(val recallFunctionWithFunction: (List<T>) -> V, val functionPara: () -> T) {
inline fun compose(crossinline f: (List<T>) -> V, vararg g: () -> T): () -> V {
return { f(g.map { it.invoke() }) }
}
fun runCompose() {
compose(recallFunctionWithFunction, functionPara).invoke()
}
}
fun functionA(l: List<Observable<Any>>): LiveData<Boolean> {
...
}
fun functionB(): Observable<Any> {
...
}
Another solution
class Test<T, V>(
val recallFunctionWithFunction: (Array<out T>) -> V,
val functionPara: () -> T,
val clazz: Class<T>
) {
companion object {
inline fun <reified T, V> create(
noinline recallFunctionWithFunction: (Array<out T>) -> V,
noinline functionPara: () -> T
) = Test(recallFunctionWithFunction, functionPara, T::class.java)
}
inline fun compose(crossinline f: (Array<out T>) -> V, vararg g: () -> T): () -> V {
return {
@Suppress("UNCHECKED_CAST")
val arr = java.lang.reflect.Array.newInstance(clazz, g.size) as Array<T>
g.forEachIndexed { index, fg -> arr[index] = fg.invoke() }
f(arr)
}
}
fun runCompose() {
compose(recallFunctionWithFunction, functionPara).invoke()
}
}
...
val t = Test.create(::functionA, ::functionB)
t.runCompose()