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.