It seems that providing implicit value of rx.Ctx.Owner
is done auto-macro-magically only when code requesting for rx.Ctx.Owner
is inside code block which will run only once. This includes object
s, val
s, lazy val
s, etc.
This example will compile without an issue because val c = ...
will evaluate only once.
object Once {
val a = Var(1)
val b = Var(2)
//no need to provide `implicit ownerCtx: rx.Ctx.Owner`
val c = Rx {
a() + b() -> Rx {a() - b()}
}
}
Similarly example mentioned in question but pasted in scala REPL.
Such limitation is because of Rx leaks problem in scala.rx library. They are present when creating higher ordered Rx variables (Rx variable which contains another Rx variable). More about an issue of leaks can be read on sala.rx project site.
As remedy to leaks - concept of rx.Ctx.Owner
was introduced and voodo-macro. This exceprt from scala.rx shows interesting parts. Note Owner
companion object and implicit def voodoo: Owner
:
object Owner extends Generic[Owner]{
object Unsafe extends Owner(???){
implicit val Unsafe: Ctx.Owner.Unsafe.type = this
}
/**
* Dark magic. End result is the implicit ctx will be one of
* 1) The enclosing RxCtx, if it exists
* 2) RxCtx.Unsafe, if in a "static context"
* 3) RxCtx.CompileTime, if in a "dynamic context" (other macros will rewrite CompileTime away)
*/
@compileTimeOnly("@}}>---: A rose by any other name.")
implicit def voodoo: Owner = macro Factories.automaticOwnerContext[rx.Ctx.Owner]
}
It turns out that static blocks of code evaluate only once and are immune of leaks. This is why voodoo
allows compiler to find implicit. Try to design code in such way.
In cases when code is not in static one and you are sure that your code will evaluate only once (scripts in test for example) the common solution is to provide Unsafe
implicit instance from Owner
companion object. Just import import Ctx.Owner.Unsafe._
then.
Here how it is done in BasicTests of scala.rx sources:
package rx
import util.{Failure, Success}
import utest._
import acyclic.file
object BasicTests extends TestSuite{
//We dont care about potential Rx leaks in BasicTest
import Ctx.Owner.Unsafe._
...