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 variablea
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 variablea
.If we call
myMethod
with a given value $v$ fora
, then it will return a closure for this anonymous function. The closure is the function (with typeInteger
$\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; }; }