I keep forgetting how closures work...

Language geek warning. I'm not going to explain closures here, I'm just going to mumble some thoughts aobut them. Read about them on Wikipedia. The short answer is that a closure is a code-block that you can pass around a pointer to. It lets you write your own replacement for for loops and while loops.

Every now and then I get interested in some language or other that has closures, and I have to figure out what they are again. It's a little bit like not being able to understand pointers in the C language until you can visualize the underlying Von Neumann Architecture underneath. There's no way to understand how closures work until you stop visualizing the traditional call stack architecture.

Since some people started discussing closures in Java recently, I figured I would try to remind myself how they work. My confusion always boils down to "What about global variables?" What happens when a closure access a global variable? I decided to go to my go-to source these days, Wikipedia. Paragraph 2 of the Implementation section says: A typical modern Scheme implementation allocates local variables that might be used by closures dynamically and stores all other local variables on the stack.

All of a sudden it made sense. If you want proper closures, you have to implement a garbage-collected runtime system, and use it for every local and global variable except for cases where the compiler can prove that certain variables cannot be accessed any closures.

So the short answer to my confusion is: You can't have closures in any language that has global variables in the sense that C and C++ have global variables. At least that's my latest understanding.


I am not sure of the global variables part. Java class static variables are like C/C++ globals except for namespaces and access check (private/public etc). With C++, namespace scoped globals is more or less same as Java class static variables. Are you thinking about assigning nested function pointer to a global variable (and calling the same after the nesting function's activation record is poped out?) Have you seen this? http://people.debian.org/~aaronl/Usenix88-lexic.pdf

Posted by A. Sundararajan on October 08, 2006 at 06:15 PM PDT #

Sure you can visualize closures in a traditional C call stack environment: just think of the GNU C compiler nested functions extension. GCC implements closures of dynamic extent by pushing a trampoline of executable code on the stack, and that trampoline encodes the address of the frame where the closure was created, so the closure's text can access the closed variables.

Closures of indefinite extent can't really be added to C, as they involve putting closed variables on a heap-allocated object instead of in a stack allocated call frame.

Posted by Nico on October 09, 2006 at 08:07 AM PDT #

And the reason you can't have true closures in C, IMO, is the lack of a GC, not the presence of global variables (LISP has both, global variables and closures, after all). Also, some Schemes put all call frames on the heap, which makes grabbing the current continuation really cheap (but it doesn't make continuations cheap).

Posted by Nico on October 09, 2006 at 08:09 AM PDT #

Thanks for commenting Nico. It was really just "closures of indefinite extent" that I had problems with. Closures of "dynamic extent" seem analagous to setjmp, so they're easier to wrap my mind around.

A. Sundararajan: My problems with "global variables" are not related to assigning a closure to a global variable, but more like how to use them safely. If all the static and global variables can have completely different values when the closure is executed, doesn't that make them hard to use? If some variables have the values they had when the closure was created, and other variables have their "latest" values, doesn't it get confusing?

I guess the answer is to use closures for small well-controlled bits of code, and avoid accessing global/static variables if you want to be able to understand your code.

Posted by Chris Quenelle on October 10, 2006 at 06:25 AM PDT #

Nico: I agree with the comment on closures of infinite extent. But, for the most to write "your own replacement for for loops and while loops" constructs, closures with dynamic extent \*may\* be sufficient.
Chris: I agree on your comments on globals.

Posted by A. Sundararajan on October 15, 2006 at 02:00 PM PDT #

Post a Comment:
Comments are closed for this entry.

Chris Quenelle


« July 2016