In perl at least, a closure doesn't have to be a function definition. It's more or less anything between a pair of braces, that serves as it's own variable scope. In Damian Conway's Object Oriented Perl, I believe he uses closures to implement the private variables of an object, so it might be misleading to say that the closure itself is an object or acts like one. In any case, something needs to be said about scope here. Wesley
How could one use a closure that's not a function definition?
Regarding the "acts as an object" comment, I was thinking of a closure like this:
sub counter { my $x = shift; return sub { print "$x\n"; $x--; }; } $h = counter(4); $g = counter(7); &$h(); # gives 4 &$h(); # gives 3 &$g(); # gives 7 &$h(); # gives 2
AxelBoldt
A closure can be used as a way to simulate static variables. For instance consider the following (slow) function:
sub fib { my $n = shift; if ($n <= 1) { return 1; } else { return fib($n-1) + fib($n-2); } }
It works, but calculating (say) fib(40) may take a while. Now let's add a private closure in which we cache results (this kind of caching is known as memoizing):
{ my %cache; sub fib { my $n = shift; if ($n <= 1) { return 1; } elsif (exists $cache{$n}) { return $cache{$n}; } else { return $cache{$n} = fib($n-1) + fib($n-2); } } }
Now the function runs much more quickly. If we had static variables (the "my $foo if 0;" bug does not count in my books!), that would be the right way to do this, but closures can do it as well.
BTW I hope that the example I gave is not too complex. I wanted to provide something that was accessible but gave an idea of why someone might choose to use closures.
IMO the example was too complex. Also, Perl is a heinous language for explaining computer science concepts (e.g., you have to use "shift" to peel off arguments --- utterly obscure --- not to mention all the other random syntactic noise that comes with Perl). I replaced it with a more basic explanation that just conveys the idea of lexical scope capture. I used ML, which has a far more concise and pseudocode-like syntax than Perl.
If you want to do a more involved programming example, IMO you should create an article for first-class function or higher-order function and write it there; or, better still add it to functional programming. The term "closure", as commonly used by language designers/implementors, refers specifically to the data structure with the code pointer and environment pointer. Programming using higher-order functions is a broader idea, and belongs in a broader article. k.lee 00:44, 24 Oct 2003 (UTC)
Re: typical implementation as "a set of values that record the values of the relevant variables in the function's lexical environment at the time of binding", this was not correct. A naive Lisp interpreter can implement a closure as a pair containing a pointer to the function and a pointer to the actual lexical environment (activation record) at the point of capture. There's no recording of values, or selection of relevant variables for capture. Wasteful and slow, but adequate. k.lee 17:27, 24 Oct 2003 (UTC)
I have just edited the page such that the Java simulation section has "final" instead of "immutable". My understanding of the term immutable in the context of Java is that it means once you have a reference to the object its internal state will never change i.e. all fields (including private ones) can be declared final and all references that the object holds are themselves to immutable objects. This property, as far as I know, is not detected or enforced by the runtime and is not necessary for a local variable to be used in an anonymous inner class. The meaning of the keyword final, on the other hand, is that the value of the variable will never change which object it references (or will never change value if a primitive). It is this that is necessary for the anonymous inner type to make use of the variable so that the runtime can simply clone the primitive values and object references of final variables on the stack when instantiating the anonymous inner class.
--Jwal 18:35, 12 Jun 2004 (UTC)