On this page:
2.1 Configuration
2.2 Adaptation
2.3 The Case of Exceptions

2 When is Dynamic Scope Useful?

There are several reasons why one would want to address the problem of implicitly passing information between software components.

2.1 Configuration

In a software system, there are potentially many aspects that one may want to customize in a local yet dynamically-scoped manner. For instance, one may want to specify that, during the execution of a certain procedure, messages printed to the standard output stream be redirected to a temporary file.

Other typical examples of configurations include user preferences, device-specific settings, etc.

Question: In Java, System.out is a global variable. How could you redirect printing to that stream temporarily? Would you face the problem mentioned above with multiple threads? Also, most system configuration information is stored in a global dictionary available at System.getProperties (). Reflect on the pitfalls of this design.

2.2 Adaptation

Another application of dynamic scope, which is directly related to configuration, is that it supports many forms of software adaptation: the ability for software to react differently based on its context of execution. Sometimes the adaptation can be done quite statically (eg. specialize the code for running on mobile devices), but sometimes the property that drives the adaptation is inherently dynamic. For instance, one might want to track security levels (eg. is this function being applied by a trusted client?) in order to determine how to compute a value (eg. encrypt result, downgrade quality of service, etc.).

Question: What other scenarios of dynamic adaptation can you think of?

2.3 The Case of Exceptions

I find the case of exception handling an interesting illustration of the need for dynamic scope. The story is dual in that exception handling relates more naturally to return values, instead of arguments.

Think about C (just for a brief moment). C does not have exceptions. So how do procedures manifest errors for others to handle? By returning error codes. And just like with intermediate functions and arguments discussed above, intermediate procedures in C must be careful to appropriately propagate error codes "upwards" until the procedure that knows how to handle the error sees it. Another very unfortunate side effect of using return values for error management is that procedures need an alternative manner to communicate the result of their computation to their callers; typically, this is done by mutating one of their arguments—making mutation pervasive in C programming...

Modern languages use exceptions for this. When one puts a try/catch block around some computation, she doesn’t know whether one procedure down the call stack will raise an exception or not. Similarly, when one raises an exception, one does not know who will handle it (if any). The language runtime system walks up the call stack (conceptually at least) to find a catch block that can handle the exception. If you think about it, this is very similar to introducing/using a dynamically-scoped variable.

Question: Write an example in Java (or your favorite language that has exceptions) that illustrates that exception handlers are bound dynamically and not lexically.

Question: If you are given a language with dynamic scope, but no exception handling support, can you build it on top of dynamically-scoped variables?