CSC447
Concepts of Programming Languages
Dynamic and Static Scope
Instructor: James Riely
What Does This Program Do?
-
What does this program do?
-
Using Scala syntax, but various different semantics
-
not just Scala's semantics
| var x:Int = 10 |
| def foo () = |
| x = 20 |
| |
| def bar () = |
| var x:Int = 30 |
| foo () |
| |
| bar () |
| println (x) |
Static Scope
-
Static scope: identifiers are
bound to the closest binding occurrence in an enclosing
block of the program code
-
Static scoping property: We can rename any
identifier, so long as we rename it consistently throughout
its scope
(and so long as the new name we have chosen does
not appear in the scope)
-
Also known as lexical scope
Dynamic Scope
-
Dynamic scope: identifiers are
bound to the binding occurrence in the closest activation
record.
-
Consistent renaming may break a working program!
Static vs Dynamic Scope
-
Scala uses static scope (prints 20)
-
Most languages do use static scope
| var x:Int = 10 |
| def foo () : Unit = |
| x = 20 |
| |
| def bar () : Unit = |
| var x:Int = 30 |
| foo () |
| |
| bar () |
| println (x) |
Static vs Dynamic Scope
Bash (prints 10):
| x=10 |
| function foo() { |
| x=20 |
| } |
| function bar() { |
| local x=30 |
| foo |
| } |
| bar |
| echo $x |
Static vs Dynamic Scope
C functions (prints 20):
| int x = 10; |
| void foo () { |
| x = 20; |
| } |
| void bar () { |
| int x = 30; |
| foo (); |
| } |
| int main () { |
| bar (); |
| printf ("x=%d\n", x); |
| } |
Static vs Dynamic Scope
C macros (prints 10):
| int x = 10; |
| #define foo() { \ |
| x = 20; \ |
| } |
| #define bar() { \ |
| int x = 30; \ |
| foo (); \ |
| } |
| int main () { |
| bar (); |
| printf ("x=%d\n", x); |
| } |
Static vs Dynamic Scope
Python (prints 20):
| def main(): |
| def foo (): |
| nonlocal x |
| x = 20 |
| |
| def bar (): |
| x = 30 |
| foo () |
| |
| x = 10 |
| bar () |
| print (x) |
| |
| main() |
Static vs Dynamic Scope
Python (prints 20):
| def foo (): |
| global x |
| x = 20 |
| |
| def bar (): |
| x = 30 |
| foo () |
| |
| x = 10 |
| def main(): |
| bar () |
| print (x) |
| |
| main() |
Python
Python global scope is not static
| def useX(): |
| print (x) |
| |
| def defX(): |
| global x |
| x = 1 |
>>> useX()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in useX
NameError: name 'x' is not defined
>>> defX()
>>> useX()
1
Static vs Dynamic Scope
-
Well-known PLs have included dynamic scoping...
-
...and later added static scoping!
Static vs Dynamic Scope
Emacs Lisp (prints "10"):
| (let ((x 10)) |
| (defun foo () |
| (setq x 20)) |
| (defun bar () |
| (let ((x 30)) |
| (foo))) |
| (bar) |
| (message (int-to-string x))) |
Static vs Dynamic Scope
Common Lisp (prints 20):
| (let ((x 10)) |
| (defun foo () |
| (setq x 20)) |
| (defun bar () |
| (let ((x 30)) |
| (foo))) |
| (bar) |
| (print x)) |
Static vs Dynamic Scope
Scheme (prints 20):
| (let ((x 10)) |
| (define (foo) |
| (set! x 20)) |
| (define (bar) |
| (let ((x 30)) |
| (foo))) |
| (bar) |
| (display x) |
| (newline)) |
Static vs Dynamic Scope
Perl (prints 10):
| local $x = 10; |
| sub foo { |
| $x = 20; |
| } |
| sub bar { |
| local $x = 30; |
| foo (); |
| } |
| bar (); |
| print ($x); |
Static vs Dynamic Scope
Perl (prints 20):
| my $x = 10; |
| sub foo { |
| $x = 20; |
| } |
| sub bar { |
| my $x = 30; |
| foo (); |
| } |
| bar (); |
| print ($x); |
CSC447 Concepts of Programming Languages Dynamic and Static Scope Instructor: James Riely