> fastOptJS
[info] Updating {file:/Users/joco/dev/scala.js/react/sjs-playaround/stable/}stable...
[info] Resolving org.eclipse.jetty#jetty-continuation;8.1.16.v20140903 ...
[info] Done updating.
[info] Compiling 4 Scala sources to /Users/joco/dev/scala.js/react/sjs-playaround/stable/target/scala-2.11/classes...
[error] /Users/joco/dev/scala.js/react/sjs-playaround/stable/src/main/scala/Demo/Main.scala:19:
[error] This Rx might leak! Either explicitly mark it unsafe (Rx.unsafe) or make an implicit RxCtx available
[error] in the enclosing scope, for example, by adding (implicit ctx: Ctx.Owner) to line 16: method frp
[error] val c = Rx{ a() + b() }
[error] ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed
[error] Total time: 2 s, completed Dec 8, 2016 6:48:28 AM
>
object Main extends js.JSApp {
def main(): Unit = {
val rootNode = dom.document.getElementById("playground")
ReactDOM.render(EditableSortableListDemo.c(), rootNode)
frp()
}
def frp()(implicit ctx: Ctx.Owner)={
import rx._
val a = Var(1); val b = Var(2)
val c = Rx{ a() + b() }
println(c.now) // 3
a() = 4
println(c.now) // 6
}
}
> fastOptJS
[info] Compiling 1 Scala source to /Users/joco/dev/scala.js/react/sjs-playaround/stable/target/scala-2.11/classes...
[error] /Users/joco/dev/scala.js/react/sjs-playaround/stable/src/main/scala/Demo/Main.scala:16: No implicit Ctx.Owner is available here!
[error] frp()
[error] ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed
[error] Total time: 1 s, completed Dec 8, 2016 7:11:06 AM
>
a.update
before. The difference between using a.now
and a()
on the right hand side is that a()
can be used only inside reactive context. a.now
can be used outside reactive context in which it gives the current value of a
and inside reactive context in which it doesn't add a dependency to a
from the reactive variable that the context is computing. Contrast this with using a()
inside the context which adds a dependency
a() = 5
is exactly the same as a.update(5)
I don’t think this has anything to do with map
or functor laws, as replacing map
with the corresponding Rx
construct leads to the same problem:
import $ivy.`com.lihaoyi::scalarx:0.3.2`, rx._
object Example {
val v1 = Var(0)
val v2 = Rx { v1() }
val v22 = Rx { v1() }
val v23 = Rx { v22() }
val v3 = Rx { v23() }
def q(implicit trackDependency: Ctx.Data) = {
if (v1() == 0) v2()
else {
val b = v3() != v2()
if (b)
103
else
17
}
}
val v = Rx { q }
val list = {
var result = List.empty[Int]
val obs = v.trigger { result = result :+ v.now }
v1() = 1
v1() = 2
result
}
}
println(Example.list)
This prints List(0, 103, 17)
instead of List(0, 17)
, too.
Hi,
I've got a problem with calling Futures out of Rx.
Just copy and paste the following code into ScalaFiddle:
import rx._
import rx.async._
import scala.concurrent.Future
import scala.concurrent.Promise
import scala.concurrent.ExecutionContext.Implicits.global
def request(id: Int): Future[String] = {
val p = Promise[String]()
js.timers.setTimeout(500) {
println(s"Request: $id")
p.success(id.toString)
}
p.future
}
val id = Var[Int](0)
val idString = id.flatMap(i => request(i).toRx("..."))
id() = 10
println("End...")
And you fall into a loop, with the following output:
End...
Request: 0
Request: 10
Request: 10
Request: 10
Request: 10
Request: 10
Request: 10
Request: 10
etc....
Is this a known behaviour? or is this a bug?
Is there a workaround for this kind of pattern?
Thanks for your help.
Roll
@rreckel Yea, currently the way flatMap works, it recreates the inner rx whenever the inner rx changes - this interacts poorly with toRx because, as you see in your test, it throws it in an infinite loop.
Im having a hard time coming up with an alternate definition of toRx that actually works within flatmap and am considering just removing it all together.
So ive been playing around with alternatives, and this seems to work:
implicit class FutureCombinators[T](val v: rx.Rx[Future[T]]) extends AnyVal {
def flatten(initial: T)(implicit ec: ExecutionContext, ctx: Ctx.Owner): Rx[T] = {
var result = Var(initial)
v.foreach { x => x.foreach(result.update) }
result
}
}
And its used this way:id.map { x => request(x) }.flatten("...")