(I wrote the original version of this page in 2002. I've made a few minor edits and added a comparison with Java's anonymous inner classes)
I briefly worked with a team that used Perl to implement high availability web applications. When discussing the language with the team’s technical lead, I pointed out that I was impressed with the fact that Perl implemented closures. Having written a Scheme interpreter, I considered closures a fundamental component of modelling procedures.
This led to a discussion of what was a closure, and what was it good for?
A closure encapsulates the execution of a one or more operations for side effects and/or the return of a value in the environment of the function’s definition where the closure was created.From this definition, all functions, procedures, and methods in languages such as Java and Visual Basic are closures. When a programmer refers to a language as implementing closures, (s)he is really saying that the language permits the creation of arbitrary closures at run time. Scheme aficionados would say that languages like Perl, Lisp, and Ruby support first class closures: closures can be arbitrarily created and assigned as values to variables or returned from functions.
Since contemporary programming languages are lexically scoped, the environment of the function refers to the variables in scope at the time the function is defined. This includes temporary variables, variables that are normally created on some sort of stack and discarded when they “go out of scope.” When a closure is created, variables in scope must be preserved until the closure itself ceases to exist.
Here’s a Ruby closure demonstrating the fact that it ‘captures’ a variable in the scope of its definition:
def makeCounter
var = 0
lambda do
var +=1
end
end
c1 = makeCounter
c1.call
c1.call
c1.call
c2 = makeCounter
puts "c1 = #{c1.call}, c2 = #{c2.call}"
The two important things from this example are:
Although var is no longer in scope once makeCounter returns, Ruby saves it for use in the closure.
Each invocation of makeCounter creates a different var. The two counters do not interfere with each other.
What can you do with closures? Here’s something a bit more useful, a call-by-need thunk factory:
def delay(&procToDelay)
value = nil
return lambda do
if value.nil?
value = procToDelay.call()
else
value
end
end
end
def force(thunk)
thunk.call()
end
foo = delay do
puts "thinking about foo"
"fu"
end
bar = delay do
puts "thinking about bar"
"british american racing"
end
puts force foo
puts force bar
puts force foo
puts force bar
In this example, you have a simple facility for memoizing closures: they can be called repeatedly, but they only evaluate their operations once (provided the retun value is not nil). Obviously, this should not be combined with the previous example: call-by-need thunks are useful when there are no side effects of their evaluation.
Why Java's Anonymous Inner Classes do not implement closures
At first glance, an anonymous inner class in Java looks like it captures an environment. It has access to its enclosing instance's members. That looks an awful lot like the way a closure captures its environment.
But an anonymous inner class cannot access method variables or parameters. This is a crippling limitation. Consider:
interface Transformer {
int transform (int what);
}
class TransformerConstructionKit {
public static Transformer makeMultiplier (int timesWhat) {
return new Transformer () {
public int transform (int what) {
return what * timesWhat;
}
};
}
}
This is illegal in Java for some reason. Ok, I know what the reason is. But I don't have to like it, do I?