I'm going a little crazy here. I'm trying to create an Observable<BigDecimal>
extension function (against RxJava 2.x) to emit the average of the emissions, but I'm getting a compile error with the Single.zip()
function. Does anybody have any ideas what I'm doing wrong? I tried to be explicit with all my types too and that didn't work...
import io.reactivex.Observable import io.reactivex.Single import java.math.BigDecimal fun Observable<BigDecimal>.sum() = reduce { total, next -> total + next } //compile error fun Observable<BigDecimal>.average() = publish().autoConnect(2).let { Single.zip(it.sum().toSingle(), it.count()) { sum, count -> sum / BigDecimal.valueOf(count) } }
RxJava is a library that provides an Rx framework for Java-based projects such as Android apps. RxJava can be used even when using the Kotlin language for app development.
RxJava, once the hottest framework in Android development, is dying. It's dying quietly, without drawing much attention to itself. RxJava's former fans and advocates moved on to new shiny things, so there is no one left to say a proper eulogy over this, once very popular, framework.
Type inference mostly does not work for rxJava2. It's not a type inference problem actually. Kotlin usually generates extension methods to that replaces SAM with kotlin functional types, but this technic does not work for overridden methods for some reason.
More details here https://youtrack.jetbrains.com/issue/KT-13609
As an option, you could try to specify types for lambda arguments
fun Observable<BigDecimal>.average() = publish().autoConnect(2).let { Single.zip(it.sum().toSingle(), it.count(), BiFunction { sum: BigDecimal, count: Long -> sum / BigDecimal.valueOf(count) }) }
Type inference is failing for some reason, there must be somehow multiple combinations of types that could be inferred in this context.
You can specify the types explicitly with a more traditional (and unfortunately more verbose) syntax, like this:
fun Observable<BigDecimal>.average() = publish().autoConnect(2).let { Single.zip(it.sum().toSingle(), it.count(), BiFunction<BigDecimal, Long, BigDecimal> { sum, count -> sum / BigDecimal.valueOf(count) }) }
Update:
I've just found out while working on a similar problem that the actual problem here is that Kotlin isn't able to infer which Single.zip
overload you're trying to call. From the official documentation:
If the Java class has multiple methods taking functional interfaces, you can choose the one you need to call by using an adapter function that converts a lambda to a specific SAM type. Those adapter functions are also generated by the compiler when needed.
So it turns out that using the more explicit SAM constructor solves this in itself, and gives you type inference back (basically, my previous answer was using a longer syntax than was actually required):
fun Observable<BigDecimal>.average(): Single<BigDecimal> = publish().autoConnect(2).let { Single.zip(it.sum().toSingle(), it.count(), BiFunction { sum, count -> sum / BigDecimal.valueOf(count) }) }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With