1

I wanted to create an Observable from an array of Observables like this:

package rxtest

import concurrent._
import concurrent.ExecutionContext.Implicits.global

import rx.lang.scala._
import rx.lang.scala.JavaConversions._
import rx.lang.scala.schedulers._

object A extends App {
    val ps = Array.fill(3)(Promise[Int]())
    val os = ps map {
            p => Observable from p.future observeOn NewThreadScheduler()
        }
    val v = rx.Observable.merge(os map toJavaObservable)
}

This program does not compile since Observable has several overloaded methods all called merge:

[error] /home/xgp/work/rxtest/src/main/scala/rxtest/A.scala:15: overloaded method value merge with alternatives:
[error]   [T](x$1: Array[rx.Observable[_ <: T]])rx.Observable[T] <and>
[error]   [T](x$1: rx.Observable[_ <: rx.Observable[_ <: T]])rx.Observable[T] <and>
[error]   [T](x$1: Iterable[_ <: rx.Observable[_ <: T]])rx.Observable[T]
[error]  cannot be applied to (Array[rx.Observable[_ <: Int]])
[error]     val v = rx.Observable.merge(os map toJavaObservable)
[error]                           ^
[error] one error found

Then I wanted to remove the overloading with the help of another Java class:

public class RxUtils {
    public final static <T> Observable<T> merge(Observable<? extends T>[] os) {
        return Observable.merge(os);
    }
}

The Scala code became (only the relevant part is listed here):

val ps = Array.fill(3)(Promise[Int]())
val os = ps map {
        p => Observable from p.future observeOn NewThreadScheduler()
    }
val v = RxUtils.merge(os map toJavaObservable)

This program still does not compile:

[error] /home/xgp/work/rxtest/src/main/scala/rxtest/A.scala:17: no type parameters for method merge: (os: Array[rx.Observable[_ <: T]])rx.Observable[T] exist so that it can be applied to arguments (Array[rx.Observable[_ <: Int]])
[error]  --- because ---
[error] argument expression's type is not compatible with formal parameter type;
[error]  found   : Array[rx.Observable[_ <: Int]]
[error]  required: Array[rx.Observable[_ <: ?T]]
[error]     val v = RxUtils.merge(os map toJavaObservable)
[error]                     ^
[error] /home/xgp/work/rxtest/src/main/scala/rxtest/A.scala:17: type mismatch;
[error]  found   : Array[rx.Observable[_ <: Int]]
[error]  required: Array[rx.Observable[_ <: T]]
[error]     val v = RxUtils.merge(os map toJavaObservable)
[error]                              ^
[error] two errors found

I have three questions:

  1. How to call the merge method with pure Scala like in the first case?
  2. Why does the second program not compile?
  3. How to call the merge method in the above RxUtils class in Scala?
user2595776
  • 304
  • 1
  • 10
  • If you are really interested in black magic of Java and Scala generic, check how RxScala implements `flatten`: https://github.com/ReactiveX/RxScala/blob/a385e1a474a05af5173d3a6c5f380b0f87b50dff/src/main/scala/rx/lang/scala/Observable.scala#L2669 – zsxwing May 02 '16 at 19:06

1 Answers1

2

I'm really confused with what you're doing here. Why do you mix rx.Observable and rx.lang.scala.Observable. Just choose either one of them: if you're working in Scala, choose the latter; if you're writing Java code, choose the former!

I also want to point you to this page, which compares both kinds of Observable.

Regarding your first program, if I'm correct the type of ps is Array[Promise[Int]], so os must have the type Array[Observable[Int]]. If you want to merge all of them into one single Observable, you can follow the link above and search for merge(Array<Observable<? extends T>>) in the left column. Turns out, you can write this in Scala as Observable.from(os).flatten or os.toObservable.flatten.

Regarding the second and third question: I haven't really checked this, but it probably has to do with covariance differences between Java and Scala. Probably helping the type system with providing some extra type information will do the trick. But I guess, if you just stay in the Scala language and use the RxScala library as it is meant to be, you will not have to deal with problems like this at all.

zsxwing
  • 20,270
  • 4
  • 37
  • 59
RvanHeest
  • 869
  • 6
  • 12