Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve implicit convertion #195

Closed
letientai299 opened this issue Jun 11, 2016 · 4 comments
Closed

Improve implicit convertion #195

letientai299 opened this issue Jun 11, 2016 · 4 comments
Milestone

Comments

@letientai299
Copy link

letientai299 commented Jun 11, 2016

The following Scala code won't compile

import rx.lang.scala.Observable
object Solution {
  def main(args: Array[String]): Unit = {
    Observable.create[Int](s => s.onNext(1))
      .subscribe(println(_))
  }
}

While the same thing in Java works fine.

import rx.Observable;
public class Main {
  public static void main(String[] args) {
    Observable.create(s -> s.onNext(0))
        .subscribe(System.out::println);
  }
}

Also, in the following compilable version, we shouldn't have to explicit add Int as the type param;

import rx.lang.scala.{Observable, Subscriber}
object Solution {
  def main(args: Array[String]): Unit = {
    Observable.create[Int](
      s => {
        s.onNext(1)
        Subscriber()
      }
    )
      .subscribe(println(_))
  }
}

Edit
Remove the redundant call to Scheduers.newThread() in the last snippet. That's related to another issues I reported to Jetbrains (you can find it here).

@zsxwing
Copy link
Member

zsxwing commented Jun 11, 2016

Actually, the Java compiler doesn't infer the correct type. It just thinks that s is java.lang.Object. You can change your codes as follows:

Observable.create(s -> s.onNext(0))
            .subscribe(i -> System.out.println(i + 1));

and it cannot be compiled.

I'm not sure how the Scala compiler works. But maybe the Scala compiler behavior is better as it refuses to use a wrong type in such case.

@letientai299
Copy link
Author

Thanks @zsxwing for pointing out that i (in your example) is just java.lang.Object. By, adding <Integer> into the method, the code can compile.

Observable.<Integer>create(s -> s.onNext(0))
            .subscribe(i -> System.out.println(i + 1));

So Int is needed to make Scala compiler understand that s is Observer[Int].

But s => s.onNext(0) is Observer[Int] => Unit, and therefor, the Scala code still cannot compile without Subscriber(). That statement is nothing but make the code more verbose compare to the Java version.

Anyway we could improve that?

@samuelgruetter
Copy link
Collaborator

The problem is that in order to translate a Java program doing Observable.xxx to Scala, you can't always just write Observable.xxx in Scala, because some methods have different names. So you should read the comparison table, which contains the following line:

Java method Scala method
create(OnSubscribe<T>) apply(Subscriber[T] => Unit)

So you can write your example in Scala as follows:

Observable.apply[Int](s => s.onNext(1))
      .subscribe(println(_))

or equivalently

Observable((s: Subscriber[Int]) => s.onNext(1))
      .subscribe(println(_))

The create method of the Scala Observable is a relict of ancient times, when you passed an Observer[T] => Subscription function to create instead of a Subscriber[T] => Unit function. This relict was removed in RxJava, but not in RxScala.

I agree that this is confusing and should be improved, thank you for pointing it out. I suggested to change this here.

@zsxwing
Copy link
Member

zsxwing commented Jun 17, 2016

Closing this since Observable.create has been deprecated in #196

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants