Lexical and Dynamic Scoping
lexical scoping
- if
g
is defined inf
theng
inheritsf
’s bindings - the environment is defined by static code structure
- what you see in most PLs (C, C++, SML, Java, …)
example
fn main() {
let x = "A";
let foo = || x;
let bar = || {
let x = "B";
foo()
};
println!("x = {}", bar());
}
prints x = "A"
dynamic scoping
- if
f
callsg
theng
inheritsf
’s bindings - the environment is defined by calls
- the scope of bindings is determined dynamically
example
(set 'x '10)
(defun foo (x) (bar))
(defun bar () (print x))
(foo '5)
; 5
note that 5
is printed and not 10
representation
- local bindings are represented by a dictionary
- dictionary maps names to entities
- the environment is represented by a back-pointer to the most recent stack frame
- basically a stack of dictionaries
- search for a name is carried out by searching in the stack of dictionaries
question 1
write a program that prints “DYN” if the language uses dynamic scoping and “LEX” if it uses lexical scoping.
...
const char *x = "LEX";
const char *foo() { return x; }
int main() {
const char *x = "DYN";
printf(foo());
}
question 2
can a language with static typing use dynamic scoping?
answer - it’s possible but very awkward making it an unlikely combination
fun foo () = x;
fun bar () = x + 5;
fun baz (x: float) = bar ();
- what’s the type of
foo
? - what’s the type of
bar
? - should
baz
pass typechecking?