Loosely put, closures take a blob of code and the
bindings of some
variable names to variables and return a thing which can be executed
like the blob of code, but, while it's executing the code, the
name<->variable mappings saved in the closure are temporarily
reinstated.
In other words, "static local variables"?
In some respects. However, each closure contains its own distinct set
of values; most languages' "static local variables" don't work that
way.
As a really simple example, consider (to use Lisp as the language,
since that's what I'm most familiar with practical closures in; I'm
using my own Lisp here, which is pretty close to Zetalisp in the
relevant respects):
(defun make-adder (n) #'(lambda (x) (+ x n)))
Then
(setq a4 (make-adder 4))
(setq a10 (make-adder 10))
a4 and a10 are then closures. Each one has (lambda (x) (+ x n)) as
its
code blob; its binding list includes a binding of n to some value - 4,
in the case of a4, or 10, in the case of a10.
(funcall a4 7) -> 11
(funcall a10 7) -> 17
Whereas, in C, which doesn't have closures but does have static local
variables,
static int n;
static int adder(int x) { return(x+n); }
static int (*make_adder(int val))(int)
{
n = val;
return(&adder);
}
the function returned by make_adder will always add the last value
passed to make_adder, regardless of which call's return value is
called. That is, after
int (*a4)(int);
int (*a10)(int);
a4 = make_adder(4);
a10 = make_adder(10);
Then (*a4)(7) gives 17, not 11 - though if called between the two
make_adder calls, it returns 11. This is because the returned
pointers
are _not_ closures; the binding of the name n in adder to the storage
location it refers to is fixed, and all those references refer to the
same location. (Actually, I've seen it said that there's an effort
afoot to get closures into C, along with anonymous code blocks and
various other things. I think that is spectacularly misguided; if
they
want Lisp, they know where to find it.)
From the 3 explanations (Conner,Assumpcao,Mouse) I have seen so far
in this discussion, a "closure" appears to be the functional-
programming terminology/equivalent for what in OOP would be an
"instance of an object". An instance of an object provides the code
(methods) and configuration and state (private properties) accessed
via a single reference (handle).
The above problem would be solved in OOP with a simple object
(make_adder) with a method (adder) and an internal/private property
(n) assigned in the object instance constructor. The only difference
I see is in the case of the closure the code/method does not have an
external name to denote it as there is only one code-block/method for
the closure.
I am a functional-programming-illiterate, so the discussion and
explanations have been interesting.
So is this (closure vs. object-instance) just different worlds with
different syntax and terminology? That is, leaving aside the
functional-programming vs. procedural-programming world differences
is there something else to significantly distinguish a closure from
an object-instance?