Skip to content

Commit a29a386

Browse files
Merge pull request ReactiveX#455 from samuelgruetter/scalaadaptor
Scala Adaptor: TODO list and documentation
2 parents 2bb0bb2 + 28104ea commit a29a386

File tree

2 files changed

+76
-31
lines changed

2 files changed

+76
-31
lines changed

language-adaptors/rxjava-scala/TODO.md

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,50 @@
22
TODOs for Scala Adapter
33
-----------------------
44

5-
This is a (probably incomplete) list of what still needs to be done in the Scala adaptor:
5+
This is a (probably incomplete) list of what still needs to be done in the Scala adaptor.
6+
7+
TODOs which came up at the meeting with Erik Meijer on 2013-10-11:
8+
9+
* Rename the factory methods in `object Observable`, considering that the most important is the one taking an `Observer => Subscription` function (the "king" according to Erik). Thunk to Subscription conversion (?), also consider Jason's [comments](https://github.com/Netflix/RxJava/commit/c1596253fc5567b7cc37d20128374d189471ff79). A useful trick might also be to have `apply(T, T, T*)` instead of just `apply(T*)`.
10+
* Factory methods for observables and instance methods should take implicit scheduler, default is different per method (Isn't this a contradiction? In other words: If I call a method without providing a scheduler, should the default scheduler be used or the implicit that I provided?) Find in .NET source the list of which schedulers goes with which operators by default. If no other default, use NewThreadScheduler. Note that there are methods in Scala Observable which should have an overload taking a Scheduler, but do not yet have it! Also remember Erik saying that he would like to "minimize magically injected concurrency".
11+
* Bring `BooleanSubscription`, `CompositeSubscription`, `MultipleAssignmentSubscription` to Scala, `compositeSubscription.subscription = ...`instead of setter method, add on `CompositeSubscription` should be `+=`
12+
* Convert executor to scheduler
13+
* Java Scheduler methods take `state` arguments (they were needed to schedule work on a different machine, but are now considered a bad idea). Remove these `state` arguments from all Scala schedulers.
14+
* Check if TestScheduler added in 0.14.3 is sufficient
15+
* Infinite Iterables: the java Observable.from version unfolds an iterable, even it is infinite. Should be fixed in java.
16+
* subscribe methods: There are many overloads, but still not all combinations one might need. Make this nicer and complete, maybe using default arguments. Also try to make sure that `subscribe(println)` works, not only `subscribe(println(_))`. `foreach(println)` works on collections, but not on `subscribe(println)`, because subscribe is overloaded.
17+
* Currently all Swing examples use Swing directly, without using the Scala wrappers around Swing. Make sure that everything is nice if the Scala wrappers around Swing are used, eg `Reaction { case clicked: ButtonClicked => … }` -- avoid default case, check out the hooks for partial function applyOrElse to avoid double pattern matching
18+
* There are no examples yet using `async`, but `async` will be used in the course. Write examples and check if everything works as expected when combined with `async`.
19+
* Futures: For the moment, just add a Future->Observable converter method to `object Observable`. Later, think if `Future[T] extends Observable[T]`.
20+
* Operator `delay`: Once Erik has commented on [this](https://github.com/Netflix/RxJava/pull/384), make sure this operator is added accordingly to RxJava and then to RxScala
21+
* add wrappers or aliases for `AsyncSubject<T>`, `BehaviorSubject<T>`, `PublishSubject<T>`, and `ReplaySubject<T>`
22+
* go through Erik's code that he showed at the meeting and check if everything can now be done nicely
23+
* get Erik's slides from the course and check if they are compatible with the library
24+
25+
Some more TODOs:
626

727
* Integrating Scala Futures: Should there be a common base interface for Futures and Observables? And if all subscribers of an Observable wrapping a Future unsubscribe, the Future should be cancelled, but Futures do not support cancellation.
828
* Add methods present in Scala collections library, but not in RxJava, e.g. aggregate à la Scala, collect, tails, ...
929
* combineLatest with arities > 2
10-
* Implicit schedulers?
1130
* Avoid text duplication in scaladoc using templates, add examples, distinction between use case signature and full signature
12-
* other small TODOs
31+
* other small TODOs in source code
32+
* always: keep Scala Observable in sync with Java Observable
33+
34+
35+
### Appendix:
36+
37+
`println` example:
38+
39+
List(1, 2).foreach(println)
40+
Observable(1, 2).toBlockingObservable.foreach(println)
41+
42+
Observable(1, 2).subscribe(println) // does not work
43+
44+
class Ob[+T] {
45+
def subscribe(onNext: T => Unit) = ???
46+
}
47+
val o2 = new Ob[Int]
48+
o2.subscribe(println) // works
1349

1450

15-
(Implicit) schedulers for interval: Options:
1651

17-
```scala
18-
def interval(duration: Duration)(implicit scheduler: Scheduler): Observable[Long]
19-
def interval(duration: Duration)(scheduler: Scheduler): Observable[Long]
20-
def interval(scheduler: Scheduler)(duration: Duration): Observable[Long]
21-
def interval(duration: Duration, scheduler: Scheduler): Observable[Long] && def interval(duration: Duration): Observable[Long]
22-
````

language-adaptors/rxjava-scala/src/test/scala/rx/lang/scala/CompletenessTest.scala

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,55 @@
11
package rx.lang.scala
22

3-
import scala.reflect.runtime.universe._
4-
import org.scalatest.junit.JUnitSuite
5-
import org.junit.Test
6-
import rx.util.functions._
7-
import scala.collection.SortedSet
3+
import java.util.Calendar
4+
85
import scala.collection.SortedMap
6+
import scala.reflect.runtime.universe
7+
import scala.reflect.runtime.universe.Symbol
8+
import scala.reflect.runtime.universe.Type
9+
import scala.reflect.runtime.universe.typeOf
10+
911
import org.junit.Ignore
10-
import java.lang.reflect.Modifier
11-
import java.util.Date
12-
import java.util.Calendar
12+
import org.junit.Test
13+
import org.scalatest.junit.JUnitSuite
1314

15+
/**
16+
* These tests can be used to check if all methods of the Java Observable have a corresponding
17+
* method in the Scala Observable.
18+
*
19+
* These tests don't contain any assertions, so they will always succeed, but they print their
20+
* results to stdout.
21+
*/
1422
class CompletenessTest extends JUnitSuite {
1523

24+
// some frequently used comments:
1625
val unnecessary = "[considered unnecessary in Scala land]"
17-
1826
val deprecated = "[deprecated in RxJava]"
19-
2027
val averageProblem = "[We can't have a general average method because Scala's `Numeric` does not have " +
2128
"scalar multiplication (we would need to calculate `(1.0/numberOfElements)*sum`). " +
2229
"You can use `fold` instead to accumulate `sum` and `numberOfElements` and divide at the end.]"
23-
2430
val commentForFirstWithPredicate = "[use `.filter(condition).first`]"
25-
2631
val fromFuture = "[TODO: Decide how Scala Futures should relate to Observables. Should there be a " +
2732
"common base interface for Future and Observable? And should Futures also have an unsubscribe method?]"
2833

29-
val correspondence = defaultMethodCorrespondence ++ Map(
34+
/**
35+
* Maps each method from the Java Observable to its corresponding method in the Scala Observable
36+
*/
37+
val correspondence = defaultMethodCorrespondence ++ correspondenceChanges // ++ overrides LHS with RHS
38+
39+
/**
40+
* Creates default method correspondence mappings, assuming that Scala methods have the same
41+
* name and the same argument types as in Java
42+
*/
43+
def defaultMethodCorrespondence: Map[String, String] = {
44+
val allMethods = getPublicInstanceAndCompanionMethods(typeOf[rx.Observable[_]])
45+
val tuples = for (javaM <- allMethods) yield (javaM, javaMethodSignatureToScala(javaM))
46+
tuples.toMap
47+
}
48+
49+
/**
50+
* Manually added mappings from Java Observable methods to Scala Observable methods
51+
*/
52+
def correspondenceChanges = Map(
3053
// manually added entries for Java instance methods
3154
"aggregate(Func2[T, T, T])" -> "reduce((U, U) => U)",
3255
"aggregate(R, Func2[R, _ >: T, R])" -> "foldLeft(R)((R, T) => R)",
@@ -158,8 +181,7 @@ class CompletenessTest extends JUnitSuite {
158181
def getPublicInstanceAndCompanionMethods(tp: Type): Iterable[String] =
159182
getPublicInstanceMethods(tp) ++
160183
getPublicInstanceMethods(tp.typeSymbol.companionSymbol.typeSignature)
161-
162-
184+
163185
def printMethodSet(title: String, tp: Type) {
164186
println("\n" + title)
165187
println(title.map(_ => '-') + "\n")
@@ -204,12 +226,6 @@ class CompletenessTest extends JUnitSuite {
204226
.replaceAll("(\\w+)\\(\\)", "$1")
205227
}
206228

207-
def defaultMethodCorrespondence: Map[String, String] = {
208-
val allMethods = getPublicInstanceAndCompanionMethods(typeOf[rx.Observable[_]])
209-
val tuples = for (javaM <- allMethods) yield (javaM, javaMethodSignatureToScala(javaM))
210-
tuples.toMap
211-
}
212-
213229
@Ignore // because spams output
214230
@Test def printDefaultMethodCorrespondence: Unit = {
215231
println("\nDefault Method Correspondence")

0 commit comments

Comments
 (0)