1

バージョン 0.3.1のscala.rxを使用した基本的な hello world の例を次に示します。

が不足しているため、コンパイルされませんimplicit ownerCtx: rx.Ctx.Owner。このインスタンスを取得するにはどうすればよいですか?

import rx._
val a = Var(1)
val b = Var(2)
val c = Rx{ a() + b() }

This Rx might leak! Either explicitly mark it unsafe (Rx.unsafe) or ensure an implicit RxCtx is in scope!
[error]     val c = Rx{ a() + b() }
[error]               ^
[error] one error found

興味深いのは、scala REPL で動作することです!?

scala> import rx._
val a = Var(1)
val b = Var(2)
val c = Rx{ a() + b() }
import rx._

scala> a: rx.Var[Int] = Var@2c(1)
scala> b: rx.Var[Int] = Var@2f(2)
scala> c: rx.Rx.Dynamic[Int] = Rx@d1(3)
scala> 

アップデート:

コードを追加した後、implicit val ctx = Ctx.Owner.Unsafeコンパイルします。しかし、これは安全ではないようです...

4

1 に答える 1

0

の暗黙的な値の提供は、要求しているコードが一度だけ実行されるコードブロック内にある場合にのみ、自動的にマクロ魔法的にrx.Ctx.Owner行われるようです。これには、s 、s、s などが含まれます。rx.Ctx.Ownerobjectvallazy val

val c = ...この例は、一度しか評価されないため、問題なくコンパイルされます。

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()}
  }
}

同様に、問題で言及されている例ですが、scala REPL に貼り付けられています。

このような制限は、scala.rxライブラリのRx リークの問題によるものです。これらは、高次の Rx 変数 (別の Rx 変数を含む Rx 変数) を作成するときに存在します。リークの問題の詳細については、sala.rx プロジェクト サイトを参照してください。

リークの救済策として - の概念rx.Ctx.Ownerが導入され、voodo-macro が導入されました。この scala.rx からの抜粋は、興味深い部分を示しています。Ownerコンパニオン オブジェクトと に注意して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]
}

コードの静的ブロックは一度しか評価されず、リークの影響を受けないことが判明しました。voodooこれが、コンパイラが暗黙的な検索を許可する理由です。そのような方法でコードを設計してみてください。

コードが静的コードではなく、コードが 1 回しか評価されないことが確実な場合 (テスト中のスクリプトなど)、一般的な解決策は、コンパニオン オブジェクトUnsafeから暗黙的なインスタンスを提供することです。Ownerあとはインポートするだけimport Ctx.Owner.Unsafe._です。

ここでは、scala.rx ソースのBasicTestsでどのように行われるかを示します。

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._
  ...
于 2016-09-26T19:32:32.653 に答える