Две основные проблемы, которые необходимо решить:
1) Проверка типа потеряна
Используя аргумент массива Single.zip()
версия, я теряю строго типизированные аргументы.
2) Исходный аргумент не может быть обнуляемым
Я не могу отправлять обнуляемые исходные значения в качестве аргумента Single.zip()
функции
3) Мне нужна альтернатива методу, принимающему Object[]
не типизированный:
public static <T, R> Single<R> zipArray(Function<? super Object[], ? extends R> zipper, SingleSource<? extends T>... sources) ...
В haskell есть вопрос, связанный с Как я могу реализовать обобщенные «zipn» и «unzipn» в Haskell? :
И в haskell Я могу добиться этого с помощью аппликативных функторов:
f <$> a1 <*> a2 <*> a3 <*> a4 <*> a5 <*> a6 <*> a7 <*> a8 <*> a9 <*> a10 <*> a11
f :: Int -> Int -> Int -> Int -> Int -> Int -> Int -> String -> String -> String -> Int
и a1 .. a11
значения, соответствующие каждому типу
Список похожих функций есть в библиотека:
С двумя аргументами:
public static <T1, T2, R> Single<R> zip(SingleSource<? extends T1> source1, SingleSource<? extends T2> source2,BiFunction<? super T1, ? super T2, ? extends R> zipper) {
ObjectHelper.requireNonNull(source1, "source1 is null");
ObjectHelper.requireNonNull(source2, "source2 is null");
return zipArray(Functions.toFunction(zipper), source1, source2);
}
с тремя:
public static <T1, T2, T3, R> Single<R> zip(
SingleSource<? extends T1> source1, SingleSource<? extends T2> source2,
SingleSource<? extends T3> source3,
Function3<? super T1, ? super T2, ? super T3, ? extends R> zipper)
И так далее ...
Во всех этих случаях это нормально, потому что каждый аргумент типизирован. Но есть ограничение до 9 одиночных источников
В нашем проекте нам нужно больше источников, потому что у нас есть много сервисов, которые мы хотим достичь asyn c (в нашем случае было 11 аргументов).
Но проблема в том, что аргументы теряют свои сильные типы, и, что еще хуже, некоторые из них могут быть Nullable
Например, мы хотели решить эту проблему вариант использования:
//Given
val bothSubscribed = CountDownLatch(2) // Change this value to 0 to run the test faster
val subscribeThreadsStillRunning = CountDownLatch(1) // Change this value to 0 to run the test faster
val service = { s1: String,
s2: Int,
s3: String?,
s4: Int,
s5: String,
s6: String,
s7: String,
s8: String,
s9: String,
s10: String?,
s11: String ->
val result =
listOf(s1, "$s2", s3 ?: "none", "$s4", s5, s6, s7, s8, s9, s10 ?: "none", s11).joinToString(separator = ";")
Single.just("Values:$result")
}
val createSingle = { value: String ->
Observable
.create<String> { emitter ->
println("Parallel subscribe $value on ${Thread.currentThread().name}")
bothSubscribed.countDown()
subscribeThreadsStillRunning.await(20, TimeUnit.SECONDS)
emitter.onNext(value)
emitter.onComplete()
}
.singleOrError()
.subscribeOn(io())
}
val s1 = createSingle("v1")
val s2 = Single.just(2)
val s3 = null
val s4 = Single.just(4)
val s5 = createSingle("v5")
val s6 = createSingle("v6")
val s7 = createSingle("v7")
val s8 = createSingle("v8")
val s9 = createSingle("v9")
val s10 = null
val s11 = createSingle("v11")
//When
val result = Single.zipArray(
listOf(
s1,
s2,
s3,
s4,
s5,
s6,
s7,
s8,
s9,
s10,
s11
)
) { arrayResult ->
service(
arrayResult[0] as String,
arrayResult[1] as String,
arrayResult[2] as String?,
arrayResult[3] as String,
arrayResult[4] as String,
arrayResult[5] as String,
arrayResult[6] as String,
arrayResult[7] as String,
arrayResult[8] as String,
arrayResult[9] as String?,
arrayResult[10] as String
)
}
//Then
result
.test()
.awaitDone(50, TimeUnit.SECONDS)
.assertSubscribed()
.assertValues("Values:v1;2;none;4;v5;v6;v7;v8;v9;none;v11")
Как видите, могут возникнуть проблемы, если я это сделаю, например:
arrayResult[0] as String,
arrayResult[1] as Int,
arrayResult[2] as String?,
arrayResult[3] as Int,
arrayResult[4] as String,
arrayResult[5] as String,
arrayResult[6] as String,
arrayResult[7] as String,
arrayResult[8] as String,
arrayResult[9] as String?,
arrayResult[10] as String
Ошибка, потому что:
1) Ни один из * Функции 1064 * могут принимать в качестве аргумента значение, допускающее значение NULL.
2) Вы можете изменить в массиве порядок значений, и это может привести к сбою из-за проверки типов