All Articles

Lexical vs Dynamic Scope

Lexical vs Dynamic Scope

Lexical scoping is a variable look-up mechanism which resolves the value of a variable by first looking for the variable name in the vicinity of where the name was used. If the name is found, the value associated with that particular name is utilized. Otherwise, the look-up repeats itself in the next outer scope. This process could eventually reach the global scope, and if the name is not found, an error is thrown at compile time.

Examples of Lexical Scoping

Variable shadowing occurs whenever a variable declared in an inner scope takes precedence over another outer variable of same name.

x = 10

shadowX =
    let x = 100
    in x

The value of x is 100 because the name x resolves to the x located within the inner scope of shadowX. Similarly, variables located outside of functions will be used whenever no local identifier is found matching the variable name.

y = 20

noShadowing =
    let x = 100
    in y

In this other example, the value of y is 20 because no other variable y was found within the inner scope of noShadowing. A look-up starts in proximity of where y was invoked, and surfaces all the way to the global scope.

Most programming languages have lexical scoping. However, there are a few which choose to adhere to dynamic scope.

What is Dynamic Scope?

Dynamic Scope is also a variable look-up mechanism which resolves the values of its variables by first looking within the local scope. If a name is not resolved, the look-up continues in the scope of the function which invoked the current one. In other words, the look-up will try to find a name by looking at the previous stack frame. Eventually, this look-up could lead all the way to main program. In most cases, if a value is not discovered, the value of the variable is left undefined.

Examples of Dynamic Scoping

In some programming languages, like Bash, the keyword local is used to specify that a variable only exists in the scope that it is currently located in.

X=Eric
function echoX {
  echo $X 
}

function callEchoX { 
  local X=John 
  echoX
}

callEchoX # => John
echo $X # => Eric

In this example, callEchoX will print "John" because it invokes echoX which has no variable X. The function echoX will inspect the scope of callEchoX and find that the value of X is John. Similarly, echo $X will print Eric because X is found in the global scope; it does not look elsewhere.

Summary

Dynamic scoping has the advantage of changing values during runtime, which makes it usable for development environments which rely on configurations that change based on the context. Hence why Bash and Perl are popular for writing scripts at a command-line level. However, unlike lexical scoping, unknown issues may arise if the values are left unassigned.

Since compile time errors are explicit in lexical scoping, it is easier to find where problems occur before the program is activated. Its for this reason that lexical scoping is popular in most programming languages.

Published 2 Dec 2015