Lesson 13 of 15
Closures and Scoping
User-Defined Functions and Closures
The most powerful feature of a language is user-defined functions. We'll add:
fn square(x) = x * x;
What is a Closure?
A closure captures the environment where it was defined. This means a function can "remember" variables from its surrounding scope:
let a = 10;
fn addA(x) = x + a;
print addA(5); // prints 15
Implementation
A function value stores: { type: "Function", params: [...], body: <expr>, env: {...} }
When calling a user-defined function:
- Create a new environment that extends the closure's captured environment
- Bind the arguments to parameter names
- Evaluate the body in this new environment
if (node.type === "FnStatement") {
env[node.name] = {
type: "Function",
params: node.params,
body: node.body,
env: { ...env } // capture current environment
};
}
// In CallExpr evaluation:
const fn = env[node.name];
if (fn && fn.type === "Function") {
const newEnv = { ...fn.env };
fn.params.forEach((p, i) => { newEnv[p] = args[i]; });
return evaluate(fn.body, newEnv);
}
Your Task
Add fn name(params) = body; syntax. Functions should capture their enclosing environment (closures).
Node.js loading...
Loading...
Click "Run" to execute your code.