When we should use scala.util.DynamicVariable?
Solution 1:
DynamicVariable
is an implementation of the loan and dynamic scope patterns. Use-case of DynamicVariable
is pretty much similar to ThreadLocal
in Java (as a matter of fact, DynamicVariable
uses InheritableThreadLocal
behind the scenes) - it's used, when you need to do a computation within an enclosed scope, where every thread has it's own copy of the variable's value:
dynamicVariable.withValue(value){ valueInContext =>
// value used in the context
}
Given that DynamicVariable
uses an inheritable ThreadLocal
, value of the variable is passed to the threads spawned in the context:
dynamicVariable.withValue(value){ valueInContext =>
spawn{
// value is passed to the spawned thread
}
}
DynamicVariable
(and ThreadLocal
) is used in Scalatra for the same reason it's used in many other frameworks (Lift, Spring, Struts, etc.) - it's a non-intrusive way to store and pass around context(thread)-specific information.
Making HttpServletResponse
and HttpServletRequest
dynamic variables (and, thus, binding to a specific thread that processes request) is just the easiest way to obtain them anywhere in the code (not passing through method arguments or anyhow else explicitly).
Solution 2:
This is well answered by Vasil, but I'll add an additional simple example that might further help understanding.
Suppose we must use some code that uses println() to write all over stdout. We want this output to go to a log file, but we don't have access to the source.
-
println()
usesConsole.println()
-
Console.println()
(fortunately) is based on aDynamicVariable[PrintStream]
that defaults tojava.lang.System.out
-
Console
defineswithOut
that just forwards to the dynamic variable'swithValue
We can use this to simply fix our issue:
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
Solution 3:
This is a minimal snippet:
val dyn = new DynamicVariable[String]("withoutValue")
def print=println(dyn.value)
print
dyn.withValue("withValue") {
print
}
print
The output will be:
withoutValue
withValue
withoutValue