Search code examples
scopescopingdynamic-scope

procedural language understanding - static vs dynamic scoping


I am having trouble understanding the answer to a homework we got back. I believe I am getting confused on the concepts of functions being "nested", but maybe that is wrong. I am looking for some help in regards to following the assignment of dynamic and static scoping values from the following code.

x : integer -- global

procedure set_x(n : integer)
    x := n
end

procedure print_x
    write_integer(x)
end

procedure first
    set_x(1)
    print_x
end

procedure second
    x : integer
    set_x(2)
    print_x
end

// program starts here
set_x(0)
first()
print_x
second()
print_x

Static Scoping Output: 1122
Dynamic Scoping Output: 1121

My thoughts as I go through each one:

Static:

  • Run set_x(0), this makes a local variable due to the parameter of n, but since we set x to n without declaring x locally (int x =..) we then update the global x to 0.
  • Run first(), which does set_x(1), which following the same logic updates x to 1 globally. we then run print_x within first which prints the global x of 1.
  • Run print_x, which just re-prints 1.
  • Run second() we locally declare x and run set_x(2), which goes updates 2 to n. (because of the set, not the second procedure, right? We then run its print_x procedure which prints the 2.
  • Run print_x which again just dumps out the 2.
  • Resulting in 1122

Dynamic (more confused on this one)

  • Run set_x(0) which sets the x and global x to 0.
  • Run first() we hit set_x again and update x to 1. We print 1.
  • Run print_x We re-print 1.
  • Run second() We locally make x, we run set_x(2), and set global x to 2. We then print 2.
  • Run print_x Finally we re-print again and here is where I guessed 2, but the answer should 1.
  • My guess 1122, actual answer is 1121

I am confused on that last part of the dynamic and why it is a 1, and not a 2.


Solution

  • It's kind of hard to follow your reasoning in some places, because you don't say which x you think is being printed or updated, and that's pretty much the whole ball of wax.

    The big thing to remember is that static scoping (also called lexical scoping) is fully determined at compile-time. Where something is defined determines its static scope.

    Dynamic scoping is of course the converse; it's determined at run-time. Where something executes determines its dynamic scope.

    So, take a look at the set_x procedure. It has no local x of its own, and it's defined in the global scope, so under static scoping, it can only ever update the global x. This is true no matter where it is called, even within the second procedure.

    Under dynamic scoping, however, the set_x call within second updates the x which is local to second, leaving the global x unchanged.

    Notice that the very last print_x call will always print the global x, regardless of the scoping rules (because the print_x procedure is defined in the global scope, and the call to print_x is executed in the global scope). So the difference is that with static scoping, global x is 2 at the end of the program; but with dynamic scoping, global x is 1.