Fri 9 Jun 2006
Static (Lexical) vs Dynamic Scoping
Posted by dkaz under Wikipedia, Programming
While reading an article about lexical closures, I realized that I wasn’t quite clear on the difference between static and dynamic scoping (probably because I’ve been stuck in Java for so long).
With Wikipedia only a click away, let’s take a closer look at the definitions…
Static scoping
With static scoping, a variable always refers to its nearest enclosing binding. This is a property of the program text and unrelated to the runtime call stack. Because matching a variable to its binding only requires analysis of the program text, this type of scoping is sometimes also called lexical scoping. Static scope is standard in modern functional languages such as ML and Haskell because it allows the programmer to reason as if variable bindings are carried out by substitution. Static scoping also makes it much easier to make modular code and reason about it, since its binding structure can be understood in isolation. In contrast, dynamic scope forces the programmer to anticipate all possible dynamic contexts in which the module’s code may be invoked.
Correct implementation of static scope in languages with first-class nested functions can be subtle, as it requires each function value to carry with it a record of the values of the variables that it depends on (the pair of the function and this environment is called a closure). When first-class nested functions are not used or not available (such as in C), this overhead is of course not incurred. Variable lookup is always very efficient with static scope, as the location of each value is known at compile time.
Dynamic scoping
In dynamic scoping, each identifier has a global stack of bindings. Introducing a local variable with name x pushes a binding onto the global x stack (which may have been empty), which is popped off when the control flow leaves the scope. Evaluating x in any context always yields the top binding. In other words, a global identifier refers to the identifier associated with the most recent environment. Note that this cannot be done at compile time because the binding stack only exists at runtime, which is why this type of scoping is called dynamic scoping.
Generally certain blocks are defined to create bindings whose lifetime is the execution time of the block; this adds a hint of lexicality to the scoping. However, since a section of code can be called from many different locations and situations, it can be difficult to determine at the outset what bindings will apply when a variable is used. This can be beneficial; application of the principle of least knowledge suggests that code avoid depending on the reasons for (or circumstances of) a variable’s value, but simply use the value according to the variable’s definition. This narrow interpretation of shared data can provide a very flexible system for adapting the behavior of a function to the current state (or policy) of the system. However, this benefit relies on careful documentation of all variables used this way as well as on careful avoidance of assumptions about a variable’s behavior, and does not provide any mechanism to detect interference between different parts of a program. As such, dynamic scoping can be dangerous and many modern languages do not use it. Some languages, like Perl and Common Lisp, allow the programmer to choose lexical or dynamic scoping when (re)defining a variable.
Long definitions aside, I felt that the code example Wikipedia included answered all my remaining questions…
int x = 0;
int f () { return x; }
int g () { int x = 1; return f(); }
With static scoping, calling g will return 0 since it has been determined at compile time that the expression x in any invocation of f will yield the global x binding which is unaffected by the introduction of a local variable of the same name in g.
With dynamic scoping, the binding stack for the x identifier will contain two items when f is invoked: the global binding to 0, and the binding to 1 introduced in g (which is still present on the stack since the control flow hasn’t left g yet). Since evaluating the identifier expression by definition always yields the top binding, the result is 1.

June 23rd, 2006 at 3:43 pm
You have a small error in your opening text: you say “static and dynamic *typing*” when you really mean “static and dynamic *scoping*”. Static vs. dynamic typing is something completely different.
Dynamic scoping is a particular interest of mine and you can find my collection of related links at http://www.peerbox.com:8668/space/Context.
June 23rd, 2006 at 10:20 pm
Oops…Thanks, Kev.
March 13th, 2007 at 5:20 am
This is very good article. I read many articles on this but was not clear. Thanks a lot for this
March 13th, 2007 at 5:26 am
and probably that is why in perl my variables are faster than local variables.