
 1) Bindings.
 2) Open expressions,
    free variables,
    non-local references.
 3) Closing an open expression.
 4) Lexical scope.
 5) Dynamic scope.
 6) First class functions.
 7) Higher order functions.
    a) Functions as parameters to functions.
    b) Functions as return values from functions.
 8) Anonymous lambda expressions.
 9) Nested lambda expressions (nested functions).
10) When a programming language has
    a) non-local references,
    b) lexical scope,
    c) first class functions,
    d) nested functions,
    then the language's interpreter (or compiler) must implement "closures".
11) Curried functions (an important example
    of nested anonymous lambda expressions)



1) Bindings.

   A binding is an association of a variable reference
   to a variable declaration.

   var x = 5;      // this is a variable declaration
   var y = 1 + x;  // this declares y, and x is bound to the above declaration


2) Open expressions, free variables, and non-local references.

   A free variable is a variable without a binding, that is
   a variable with no declaration associated to it. Free
   variables are also called "non-local references".
   
   Some examples of open expressions. Each expression
   has at least one free variable without any
   declaration (without any binding).

      m*x + b            // three free variables

      2*x^2 - 8 = 0      // one free variable

      x^2 + y^2 = 1      // two free variables

      f(x) = a*x^2       // one free variable
      
      g(x) = m*x + b     // two free variables

      double f(double x)
      {
         return a * x * x; // one free variable
      }


3) Closing an open expression.

   A closed expression does not have any free variables.

   You close an open expression by providing a binding
   for each free variable.

   Examples of closing an open expression by providing a binding
   of each variable reference to a variable declaration. These
   examples come from math, logic, and programming languages.

      g(x,m,b) = m*x + b    // m, x, b are bound to formal parameters

      let x = 2 in 2*x^2 - 8 = 0   // x is bound to the constant 2

      int x = 2; 2*x*x - 8 == 0;   // x is bound to the variable with value 2

      let x = 1 in 2*x^2 - 8 = 0   // x is bound to the constant 1

      { x | 2*x^2 - 8 = 0 }  // x is bound to a local variable in the set definition

      There exits an x such that 2*x^2 - 8 = 0.  // x is bound by a quantifier

      For all x, 2*x^2 - 8 = 0.                  // x is bound by a quantifier

      For all x, x^2 >= 0.                       // x is bound by a quantifier

      Let y = 5.
      For all x, x*y >= 0.  // x is bound by a quantifier, y is bound to the constant 5

      { (x,y) | x^2 + y^2 = 1 } // x, y are bound to local variables in the set definition

      let a = 10 in f(x) = a*x^2    // a is bound to the constant 10

      double a = 10;
      int f(double x)
      {
         return a * x * x;  // a is bound to the global variable
      }


4) Lexical scope.

   Lexical scope is a common way for a programming language
   to determine variable bindings.

   Variable bindings are determined by how code blocks
   are nested within each other. This is completely
   determined by how you write the code and does not
   depend on the order in which the code gets executed.

   Lexical scope is also called "static scope" because
   the binding of any variable reference can be determined
   "statically" (at "compile time") by just looking at the
   code.
   
   There is more than one kind of "lexical scope". For
   example, in the following code, the x in print(x) is
   bound to the first x in most lexically scoped languages,
   but in JavaScript, the x in print(x) is bound to the
   declaration in the next line.
   
   var x = 5;      // this is a variable declaration
   {
      print(x);    // which declaration of x is this x bound to?
      var x = 50;  // this declares another variable called x
   }
   
   The languages C++, Java, Python, and JavaScript all use lexical scope,
   but they all use slightly different versions of lexical scope.
   

5) Dynamic scope.

   Dynamic scope is an obsolete way for a programming language
   to determine variable bindings.
   
   Variables references are bound to their most recently
   executed variable declaration. This is determined by
   the order in which the code gets executed.

   Here is an example that compares dynamic with lexical scope.
   Consider this C code.

      int y = 3;       // declaration of a global y
      int f(int x) {
         return x + y; // y is a non-local reference
      }
      int g(int x) {
         int y = 1;    // declaration of a local y
         return f(x);
      }
      f(0); // returns 3 (binds y reference in f to global y)
      g(0); // returns 3 with lexical scope (binds y reference in f to global y)
            // returns 4 with dynamic scope (binds y reference in f to local y in g)

   With lexical scope, here is what the environments look
   like when g(0) is called and then g calls f(x),

                       [Global Env]
                       [ y, 3     ]
                       [ f, lambda]
                       [ g, lambda]
                      /            \
                     /              \
       [Local Env, g]                [Local Env, f]
       [ y, 1       ]                [ x, 0       ]
       [ x, 0       ]

   When f looks up the value of y in its environment,
   it sees y = 3.

   With dynamic scope, here is what the environments look
   like when g(0) is called and then g calls f(x),

                     [Global Env]
                     [y, 3      ]
                     [f, lambda ]
                     [g, lambda ]
                    /|\
                     |
                     |
                     [Local Env, g]
                     [ y, 1       ]
                     [ x, 0       ]
                    /|\
                     |
                     |
                     [Local Env, f]
                     [ x, 0       ]

   When this f looks up the value of y in its environment,
   it sees y = 1 (the first y in the chain of environments),
   not y = 3.

   With lexical scope, the environments form a tree rooted at
   the global environment. The structure of this tree is
   determined by how the code has been written (but which
   environment objects are in the tree at any given time
   is determined by the execution of the code).

   With dynamic scope, the environments form a chain that
   ends with the global environment. Which environment
   objects are in this chain, and their order in the chain,
   is determined by the order in which functions get called
   while the program executes. This order is not predetermined
   by the code, so which variable declaration a variable
   reference gets bound to can depend on the order in
   which functions are called. This means that you cannot
   look at the code and always determine which declaration
   a variable will be bound to. You must run the code to
   find out. This makes dynamic scope buggy and unreliable.


6) Frist class functions.
   When function values can be stored in variables.


7) Higher order functions (this requires that functions be first class).
    a) Functions as parameters to functions.
       (downwards funarg problem)
    b) Functions as return values from functions.
       (upwards funarg problem)
    

8) Anonymous lambda expressions.


9) Nested lambda expressions (nested functions).


10) When a programming language has
   a) non-local references,
   b) lexical scope,
   c) first class functions,
   d) nested functions,
   then the programming environment must implement "closures".

C and C++ have properties (a), (b), and (d),
but C and C++ do not have (c).

Java has (a) and (b).
Java kind of has (c) (nested and inner classes).
Java kind of has (d) (using functional interfaces).
Java does not implement real closures because the
variables being closed must be (effectively) final.

Pascal has (a), (b), (c), and function parameters,
but Pascal does not have function return values.

Modula-2 and Oberon have (a), (b), (c) and (d)
but don't allow nested function as return values.

The original version of Lisp had (a), (c), and (d)
but it did not have (b) (Lisp had dynamic scope then).

All modern functional programming languages (Scheme,
Haskell, ML, F#, Scala, Clojure, etc.) have all four
properties and they implement closures.

JavaScript has all four properties and so JavaScript
implements closures, but JavaScript's version of
lexical scope is a bit unusual.

Python has all four properties and so Python
implements closures, but Python's version of
lexical scope is also a bit unusual.


11) Curried functions (an important example of nested anonymous functions)
    Partial application
