web-dev-qa-db-ja.com

いつscala.util.DynamicVariableを使うべきですか?

スカラトラのソースを読んだとき、次のようなコードがあることがわかりました。

_protected val _response   = new DynamicVariable[HttpServletResponse](null)
protected val _request    = new DynamicVariable[HttpServletRequest](null)
_

DynamicVariableという名前の興味深いクラスがあります。このクラスのドキュメントを見ましたが、いつ、なぜ使用する必要があるのか​​わかりません。通常使用されるwithValue()があります。

それを使用しない場合、それが解決した問題を解決するために、代わりにどのコードを使用する必要がありますか?

(私はscalaを初めて使用します。コードを提供できれば、それは素晴らしいことです)

46
Freewind

DynamicVariableは、ローンと動的スコープパターンの実装です。 DynamicVariableのユースケースはJavaのThreadLocalとほとんど同じです(実際のところ、DynamicVariableInheritableThreadLocal舞台裏)-囲まれたスコープ内で計算を行う必要がある場合に使用されます。すべてのスレッドには、変数の値の独自のコピーがあります。

dynamicVariable.withValue(value){ valueInContext =>
  // value used in the context
} 

DynamicVariableが継承可能なThreadLocalを使用する場合、変数の値はコンテキストで生成されたスレッドに渡されます。

dynamicVariable.withValue(value){ valueInContext =>
  spawn{
    // value is passed to the spawned thread
  }
}

DynamicVariable(およびThreadLocal)は、他の多くのフレームワーク(Lift、Spring、Strutsなど)で使用されているのと同じ理由でScalatraで使用されています。これは、保存して渡すための邪魔にならない方法です。コンテキスト(スレッド)固有の情報について。

HttpServletResponseおよびHttpServletRequest動的変数を作成する(したがって、要求を処理する特定のスレッドにバインドする)ことは、コード内の任意の場所でそれらを取得する最も簡単な方法です(メソッド引数を通過しないなど)。それ以外の場合は明示的に)。

56
Vasil Remeniuk

これはVasilによって十分に回答されていますが、理解に役立つ可能性のある簡単な例を追加します。

Println()を使用してstdout全体に書き込むコードを使用する必要があるとします。この出力をログファイルに移動させたいのですが、ソースにアクセスできません。

  • println()Console.println()を使用します
  • Console.println()(幸いなことに)は に基づく a DynamicVariable[PrintStream]デフォルトはJava.lang.System.out
  • Consoleは、動的変数のwithOutに転送するだけの withValue を定義します。

これを使用して、問題を簡単に修正できます。

def noisy() { println("robot human robot human") }
noisy() // prints to stdout
val ps = new Java.io.PrintStream("/tmp/mylog")
scala.Console.withOut(ps) { noisy() } // output now goes to /tmp/mylog file
24
overthink

これは最小限のスニペットです。

val dyn = new DynamicVariable[String]("withoutValue")
def print=println(dyn.value)
print
dyn.withValue("withValue") {
  print
}
print

出力は次のようになります。

withoutValue
withValue
withoutValue
17
Hanfei Sun