Closures and memoization
IntermediateA closure is a function that "closes over" the bindings it can see at the moment it is created — those bindings travel with the function even after the surrounding scope is gone. Memoization is a small but powerful application of that idea: a wrapper function carries a cache of past results in its closure, so repeated calls with the same arguments skip the work.
Minimal example
Every fn is a closure. Here the returned function remembers n long after
adder has returned:
The two adders share the same code but carry different captured n values —
that's the whole point of a closure.
Practical example: a counter factory
Closures shine when you want to bundle behavior with private state. Here the
atom lives inside the closure, so each call to make-counter produces an
independent counter:
c1 and c2 can't see each other's atom — encapsulation, built out of nothing
but a function and a let.
Memoization
memoize takes a function and returns a new function that caches results by
argument tuple. Two rules to keep in mind: the function must be pure (same
inputs → same output, no side effects), and the cache grows without bound, so
don't memoize functions with huge or unbounded input spaces.
A classic demo is the naive Fibonacci, whose exponential recursion collapses to linear when memoized:
Notice the recursive calls go through the memoized fib, so each subproblem
is solved at most once.
When memoization is the wrong tool
- Impure functions (I/O, randomness, time-dependent results) will return stale or wrong values from the cache.
- Cheap functions rarely benefit — the lookup itself costs something.
- Unbounded input domains turn the cache into a memory leak; reach for
core.cacheorcore.memoizeif you need eviction policies.
Check yourself
? quiz
Why does `memoize` only work safely on pure functions?
Exercise
Write make-adder so that ((make-adder 7) 3) returns 10. Then write
make-bounded-counter that takes a maximum value and returns a function
that increments a private counter but stops at max.