# Closures

Minima.l implement lexical scope closures using stack-oriented association lists. These lists are created by symbol-binding operations and are carried over by functions and lambdas.

## Example

Let's consider the following `let` operation:

``````(let ((a . 1) (b . 2)) PRG)
``````

The closure made available to `PRG` is:

``````(((a . 1) (b . 2)))
``````

## Problem definition

Symbol binding operations are operations that associate a value to a symbol. This association can either happen at the global scope or at the local scope.

Operations that impact the global scope are `def`, `setq` and `<-` to the extent that it only alters existing symbols.

Operations that impact the local scope are `let` and `<-`. The `let` operation actually creates a local scope and can be used to define lambdas as local functions:

``````(let ((fn . (\ (a b) (+ a b)))) (fn 1 2))
``````

These local scopes can be nested, and so can be these local functions:

``````(let ((fn0 . (\ (a b) (+ a b))))
(let ((fn1 . (\ (a b) (- b a))))
(fn1 (fn0 2 2) (fn0 1 1))))
``````

Local functions need to be shielded from nesting operations that redefine symbols. For instance:

``````(let ((a . 1)                  # Level 0 scope
(fn0 . (\ (x) (+ x a)))) #
(let ((a . 2))               # Level 1 scope
(fn0 3)))                  #
``````

This expression is expected to return the value `4` as symbol `a` was assigned the value `1` when the lambda was defined. To ensure that behavior, the lambda assigned to `fn0` must save the closure available at its definition site.

## Closure stack

The solution implemented in Minima.l to achieve this is a closure stack. At the bottom level of the stack is the global scope. Then, each nested local scope pushes its closure on the stack.

When symbols are resolved, Minima.l crawls up the stack of closure to find the first match. The global scope is always checked at the last resort.

When a function is defined at the global scope using `def`, its closure capture is empty. When a function is defined at the local scope using `let` and a lambda, the `lambda` function captures the closure into the generated function definition.