Lexical vs. dynamic scoping

In this blog I want to give you some examples about the difference between lexical and dynamic scoping. I will not dive into the details. You will find a lot of other resources about it.

Here is a small list:

The following JavaScript and Bash examples are almost equivalent in structure. Nevertheless they will lead to different results, because of the different scoping type these languages use.

Lexical scoping – e.g. JavaScript

In languages with lexical scope (also called static scope), name resolution depends on the location in the source code and the lexical context (also called static context), which is defined by where the named variable or function is defined.

Scope (computer science), Wikipedia
function baz() {
  const a = 2;

  function foo() {
    return a;
  }

  function bar() {
    const a = 3;
    return foo();
  }

  return foo() + bar();
}

console.log(baz());

Result

4

When baz() is executed it first defines a const a = 2, then the 2 functions foo() and bar(), finally calls both functions and returns the sum of their result.

When foo() is executed it simply returns a. But a is not definied within foo(). Since lexical scoping is based on the source code it searches for a in the enclosing context. That is the function baz() and baz() defines a = 2. Thus foo() returns 2.

Now when bar() is executed, bar() also defines a const a = 3, then calls foo() and returns the return value of foo(). Since JavaScript uses lexical scoping foo() will still return 2. Because foo() is not defined in bar() it can not see the const a = 3.

Therefore the output of the code will be 4.

Here a code pen that you can play with.

See the Pen JavaScript scoping – lexical or dynamic by René Link (@rene-link) on CodePen.


Dynamic scoping – e.g. Bash

in languages with dynamic scope the name resolution depends upon the program state when the name is encountered which is determined by the execution context (also called runtime contextcalling context or dynamic context).

Scope (computer science), Wikipedia
#!/bin/bash

function baz () {
        local a=2

        function foo () {
                return $a
        }

        function bar (){
                local a=3
                return $(foo)
        }

        foo
        local fooResult=$?

        bar
        local barResult=$?


        return $(( fooResult + barResult  ))
}

baz
bazResult=$?
echo $bazResult

Result

5

In contrast to the lexical scoping the bash example returns 5. The difference to the lexical scoping is that the foo that is called within bar resolves a to 3. This is because when a in foo is resolved it searches the call hierarchy for a and thus finds it in the bar call where it is defined as local a=3. The call hierarchy changes when the code runs. Thus this kind of scoping is named dynamic.

Leave a Reply

Your email address will not be published. Required fields are marked *