The problems with dynamic scope

(written by lawrence krubner, however indented passages are often quotes). You can contact lawrence at: lawrence@krubner.com, or follow me on Twitter.

Interesting:

That is, there is a single dynamic Var holding the “resource” on which the rest of the API operates. The DSSR is often accompanied by a with-* macro:

(defmacro with-resource [src & body]
`(binding [*resource* (acquire src)]
(try ~@body
(finally
(dispose *resource*)))))
This looks harmless enough. It’s practically a carbon copy of Clojure’s with-open macro, and it ensures that the resource will get cleaned up even if body throws an exception.

The problem with this pattern, especially in libraries, is the constraints it imposes on any code that wants to use the library. The with-resource macro severely constrains what you can do in the body:

You can’t dispatch to another thread. Say goodbye to Agents, Futures, thread pools, non-blocking I/O, or any other kind of asynchrony. The resource is only valid on the current thread.3

You can’t return a lazy sequence backed by the resource because the resource will be destroyed as soon as body returns.

You can’t have more than one resource at a time. Hence the “singleton” in the name of this pattern. Using a thread-bound Var throughout the API means that you can never operate on more than one instance of the resource in a single thread. Lots of apps need to work with multiple databases, which really sucks using this kind of library.

The last problem with this pattern is a more subtle one: hidden dependencies. The public API functions, which have global scope, depend on the state (thread-local binding) of another Var with global scope. This dependency isn’t explicitly stated anywhere in the definition of those functions. That might not seem like such a big deal in small examples, and it isn’t. But as programs (and development teams) grow larger, it’s one additional piece of implicit knowledge that you have to keep in your head. If there are seventeen layers of function calls between the resource binding and its usage, how certain are you going to be that the resource has the right extent?

Friends Don’t Let Friends Use Dynamic Scope

The alternative is easy: don’t do it. Don’t try to “solve” resource management in every library.

Post external references

  1. 1
    http://stuartsierra.com/2013/03/29/perils-of-dynamic-scope?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+StuartSierra+%28Digital+Digressions+by+Stuart+Sierra%29
Source