Free variable and closure

Free variable and closure #

Illustration #

Example.

In a previous exercise, we encountered the two following functions (renamed here $f$ and $g$, instead of $f_2$ and $g_2$):

$$f(x,y) = g(x)(y) \qquad \qquad \qquad g(x) = y \mapsto x^y$$

If we fix two values for $x$ and $y$ (e.g. 5 and 6), then from the definition of $f$:

$$f(5,6) = g(5)(6)$$

In this equation, $g(5)$ evaluates to the function $y \mapsto 5^y$.

Equivalently, we could give this function a name, e.g. $h(y) = 5^y$.

This function $h$ is called a closure. Intuitively, it only exists “at runtime”, because it depends on the value of $x$ (5 in this example).

In other words, we can think of $y \mapsto x^y$ as a “template” for a family of closures, one for each possible value of $x$.

Closures are ubiquitous in functional programming, but are also an important feature of some imperative languages (notably JavaScript, where they were initially used to simulate objects).

Definitions #

Free variables #

Definition. A method may access variables that:

  • are not arguments of the method, and
  • are declared outside of the method’s body.

These are often called free variables (or captured variables).

Example (in Java).

In the method sum below, the variable a is free.

public class MyClass(){

    int a = 5;

    ...

    int sum(int b){
        return a + b;
    }
}

Closure #

Definition. A closure is a method $m$ together with a binding for its free variables. It is interpreted as the method identical to $m$, but where free variables are replaced with their binding.

Example.

The Java method myMethod below returns a closure.

Function<Integer, Integer> myMethod(int a) {
    return x -> x + a;
}

Observe that the (anonymous) function x -> x + a has a free variable a.

If we call myMethod with a given value $v$ for a, then it will return a closure for this anonymous function. The closure is the function (with type Integer $\to$ Integer) defined by $x \mapsto x + v$. This function only exists at runtime.

For instance

Function<Integer, Integer> myClosure = myMethod(5);

// has value 11
int output = myClosure.apply(6);

Restrictions #

Some languages (like Java, JavaScript, C++, etc) restrict (or allow the user to restrict) the creation of closures, so as to reduce side effects.

Free variables and lambda expressions in Java #

Restriction. Variable that are free in a Java lambda expression must be effectively final, meaning that they cannot be modified after being initialized.

Examples. The following method is nearly identical to the one above, but the program does not compile, because the free variable a is not effectively final.

Function<Integer, Integer> myMethod(int a) {
    a += 1;
    return x -> x + a;
}

The following program does not compile either, for the same reason.

Function<Integer, Integer> myMethod(int a) {
    return x -> {
              a += 1;
              return x + a;
           };
}