Like most modern languages, Scala is lexically scoped, i.e. the scope of a variable is determined by the nesting of braces in the source code. Dynamic scoping instead makes variables available based on the nesting of function calls at runtime.
Dynamic scoping is generally considered a bad idea, because it breaks encapsulation and makes modular type-checking more difficult. Nevertheless, there are times when passing large amounts of state information between functions can be impractical. Traditionally global variables have been used for this task, however the use of any sort of global state is largely incompatible with multithreading.
There are essentially three ways to introduce dynamically scoped variables in Scala:1)
It is possible to achieve a similar effect to dynamic scoping using nested class definitions. By defining the entire state-consuming code as inner classes of a state object, and instantiating that object each time a new global state is required, all the contained code gets direct access to the state variables via the parent reference.
To avoid defining the entire program in a single file, this approach for most purposes mandates the use of component mixins in order to compose the program into a single class.
Advantages are speed and static checking. The big disadvantage though is lack of flexibility, for example it is not possible for objects to outlive their container and get access to a new set of state variables.
Scala supports passing implicit parameters when calling methods, however the parameter to pass is chosen using the type only; the name is ignored, which is almost certainly undesirable for this usage. A workaround is to use a unique ‘marker’ type for each dynamic variable, e.g.:
case class FooMarker(value : Int) case class BarMarker(value : Int) def callMe()(implicit foo : FooMarker) = println(foo.value) def test() = { implicit val foo = FooMarker(42) val bar = BarMarker(256) callMe() }
Advantages of this approach are again speed and static checking. The primary disadvantage is that the implicit parameter must be declared on every method, at every level of the call stack, so in many cases this is no better than regular parameter passing. This approach can be usefully combined with the one above however.
This approach makes use of Java’s ThreadLocal class, which provides a means to define a global variable storing a separate value for each thread. We make use of a variation on the loan pattern to ensure correct nesting, which is particularly important security-wise if thread pools are used:
class DynamicVariable[A] { private val tl = new ThreadLocal def get : A = tl.get().asInstanceOf[A] def withValue[B](x : A)(f : => B) : B = { val old = get try { tl.set(x) f } finally { tl.set(old) } } }
Instances of DynamicVariable will typically be created as global objects, so their current value can easily be accessed from any piece of code. The big disadvantage of this design is that the compiler can’t check that the variable is only used ‘in context’; it is always accessible, but may sometimes be null.
Note that Scala’s standard library now includes a DynamicVariable class, however it differs from the above in that it uses an InheritableThreadLocal, which may be inappropriate if the resource in question is stateful or has a strict lifecycle (e.g. a database connection).