Reading — step 1 of 3
Lexical Scoping and Environment Chains
Scope & Environments
Scope determines where a variable is visible. Lexical scoping (also called static scoping) means a variable's scope is determined by where it appears in the source code, not by the runtime call stack.
Block Scope
Variables declared inside a block { ... } are only visible within that block:
var x = "outer";
{
var x = "inner";
print x; // outputs: inner
}
print x; // outputs: outer
The inner x shadows the outer x within the block. When the block ends, the inner x disappears and the outer x is visible again.
Environment Chains
To implement scoping, we use a chain of environments. Each environment has a reference to its enclosing (parent) environment:
Global Environment: { x: "outer" }
↑
Block Environment: { x: "inner", enclosing: global }
Variable lookup walks the chain: check the current environment first, then the enclosing one, and so on until the global scope. If the variable is not found in any environment, it is undefined.
Variable Resolution
When looking up a variable x:
- Check the current (innermost) environment
- If not found, check the enclosing environment
- Repeat until the global environment
- If not found in global, report an error
When assigning x = value:
- Walk the chain to find where
xis defined - Update it in the environment where it was found
- If not found anywhere, report an error
Lexical vs Dynamic Scoping
In lexical scoping, a function sees the variables from where it was defined. In dynamic scoping, it sees variables from where it was called. Nearly all modern languages use lexical scoping — it is more predictable and enables closures.
Bash and old Lisps use dynamic scoping. Emacs Lisp used dynamic scoping until adding optional lexical scoping in version 24. The industry consensus is that lexical scoping is superior for most purposes.
How Python Handles Scope
Python uses the LEGB rule: Local, Enclosing, Global, Built-in. Function bodies create new scopes, but if/for/while blocks do NOT — Python has function-level scoping, not block-level. This surprises many programmers coming from C-like languages.
Your Task
Implement environment chains with parent pointers. Each block creates a new environment that encloses the current one. Variable lookup walks the chain from innermost to outermost.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…