Friday, August 25, 2006

Some people have been reacting to this proposal as if it
represents Sun's plans for the future of the language. At this
stage it is just some ideas being drawn up to address a number of
requirements in a clean and uniform framework. Other people are
working on alternative proposals, and I expect you'll see those
soon. It is too early to place bets on what, if anything, Sun
will do in this space for JDK7.

With the insights described in my last blog entry, we no longer
need two separate syntactic forms for closures. We also don't
need the "labelled" nonlocal return statement. We're updating the
draft spec with this and other changes, making it more precise,
and adding a bit of rationale. I hope to augment the brief
rationale that will appear in the draft with further explanation
here.

Closures, Inner Classes, and Concurrency

Our "solution" to concurrency issues in the original version of
the proposal was quite unsatisfying. Part of the problem was that
we could see no way to satisfy the requirements of that community
while preserving some of the most useful features of closures and
without violating the language design principles. Since then,
we've been reexamining the issue, and I think we've found a very
tidy solution.

Asynchronous use cases

To understand the solution, it is useful to characterize the
use cases for closures into two very distinct categories. The
first category, which I'll call asynchronous, are those
in which the user-privided code is not called immediately by the
API, but rather is saved to be executed from another thread or at
a later time. This includes asynchronous notification frameworks,
the concurrency framework's executors, and timer tasks. Generally
speaking these fall into a pattern in which the caller of the API
controls what will be done, but the API controls
when it will be done. These kinds of Java APIs are
widespread in practice, and are often expressed using
single-method interfaces or abstract classes. Because the code
passed into the API is invoked when its context no longer exists,
it is generally inappropriate to allow nonlocal control-flow.
Because it may be invoked from another thread, it is often
inappropriate to allow such code to access mutable local state.

The closure proposal attempts to address this category of use
case by providing the closure conversion, which converts
the user-written chunk of code into an anonymous inner class.

To make this very concrete, let's see how this would affect
they way you can submit a task to a java.util.concurrent.Executor.
The way you'd write it today (and this way of writing it will
always be available) is this:

This is a little better, though not necessarily enough by
itself to justify closures. This works because although
Executor.execute takes a Runnable as an
argument, and we wrote a closure, the closure conversion
converts it to a Runnable. Essentially, the closure
conversion builds an anonymous instance of Runnable whose
run method just invokes the closure. The closure
conversion is implemented at compile-time, generating exactly the
same code as in the first case, so there is no runtime overhead.

If we adopt an alternative invocation syntax that we're working
on to allow an abbreviated form of invocation statement for
methods involving closures (we're still working on the
specification), you would be able to write it something like this:

If this syntax doesn't mean anything to you, just imagine that
the block appearing at the end of the invocation of
ex.execute is turned into a closure and then passed as
the last argment (the only one, in this case) to execute.
That's basically what the abbreviated invocation syntax does.

This is a significant improvement compared to what you have to
write today. You could think of these uses cases as a shorthand
for creating anonymous class instances. The analogy isn't exact,
as certain details necessarily differ to get the langauge
construct to be well defined. Most importantly, the binding of
the names inside the block of code have to be based on the scope
in which the code appears, which in this case is the method
sayHelloInAnotherThread, not in the scope of the
anonymous class that will be created. Why? Well, if the meaning
of a name appearing in a block of code changes when you use it in
code passed in to method like this, then it would be a fruitful
source of Java
Programming Puzzles. That is especially true if the
scope from which the names are inherited isn't even mentioned in
the code. It gets worse when you consider that the method name to
which the closure is being passed might be overloaded, so you
can't tell when you're typechecking the block which interface you
are building.

Some people believe that what you can do with interfaces and
classes is enough, and would prefer to see no more (and possibly
less) than some abbreviated syntax for writing anonymous class
creation expressions. The most significant difference between
that approach and closures appears in the other category of use
cases.

Synchronous use cases

The other category I'll call the synchronous use
cases, in which the closures you pass to an API element are
invoked by your own thread strictly before that API element
returns control to you. There aren't many of these APIs appearing
in the JDK, usually because such APIs are rather awkward to write.
Anonymous class instances sometimes satisfy the requirement for
this category of use cases, and when they don't programmers resort
to various contortions to get their job done, or simply leave the
job half done. Let's see how far we can get, though, using only
interfaces for this category. I'll give a single example, again
motivated by the concurrency framework.

The Java synchronized statement is convenient and easy
to use, but for many purposes has been superceded by the
Lock interface in the concurrency framework. Here is how
you currently use a Lock to synchronize a snippet of
code:

Let's try to write this using only interfaces and classes, and
perhaps taking advantage of the syntactic abbreviation that we might
think of as being implemented by translation into inner classes.
The first thing we'll need is an interface that represents the
block of code that we're passing in. java.lang.Runnable
might just do it. So our first try at writing this method might
look something like this:

It would be nice if this just worked, but it doesn't quite.
The reason is that the run method of Runnable
isn't declared to throw any exception types, and specifically it
doesn't throw CheckedException. If we make something
almost like Runnable but in which the run method throws
Exception, that doesn't quite work either because the
implementation of withLock would have to declare that it
throws Exception too, and we aren't catching it in
callBigHonkingWhileHoldingLock.

The immediate problem is that the withLock method
doesn't provide exception transparency, which means that
the method throws the same exception type as the method passed in
to it. In order to get that, we'd have to make a version of
Runnable that can also throw some unspecified exception
type. We can do that with generics:

Assuming the closure conversion can automatically figure out
that it should be creating an instance of
RunnableWithException<CheckedException>, which it
should, this works just fine.

Things are a bit more complicated when the thing you're running
can throw two checked exception types; you really want to write a
version of withLock that doesn't care how many exceptions are
thrown in the block, they are all just propogated out. Let's take
it as a given that the generic type system can be extended to do
that (I don't think it's too difficult). Now we have a version of
withLock that is completely exception-transparent, and
can be invoked on a block of code that throws any set of exception
types, which will have to be declared or caught by the caller of
withLock. So far so good.

Let's take another slightly more complex example of a method
that we might want to refactor to use the new locks:

But this won't compile. The first problem is that the variable
c isn't final, but it is being accessed within an inner
class. We can easily fix that in this case by making c
final because the variable isn't assigned anywhere. If the
variable were assigned somewhere (but not in the block), we could
create a final local variable to hold a copy of the variable's
value where it is used, and use that other variable inside the
block.

There is a worse problem: the return true statement
inside the block is returning from the
RunnableWithException.run method, not
containsFred but the run method returns
void. We could solve that, perhaps, by making a new
version of Runnable-like interface that returns a
boolean. Or better yet perhaps we could add another generic
type parameter to indicate the return type of the interface's
method, and have the withLock method return the value to
its caller that was returned by the block.

So far so good... well, not quite as good as one would hope,
because the refactoring isn't straightforward and requires serious
thought from the programmer. Did you notice that the final return
statement had to move inside the block?
But Java programmers generally
speaking are smart people, and they can work out how to do this.
I'm sure they enjoy (as much as I do) spending their time puzzling
out how to coerce the language into doing what they want.

Performing a straightforward refactoring of this code to use a
method like withLock runs into a number of problems.
Let's look at the snippet of code that would become the body of
the method RunnableWithExceptionAndReturn.run

This can't possibly be the body of any method: it returns a
value in the middle of a loop, but it also falls off the end of
its execution. In order to refactor this method to use something
like withLock, we have to start reorganizing the code to
avoid these problems. We could move reportMissingFred(c);
into the synchronized block, but that changes the behavior of the
program. Another idea is to use a boolean state
value that is returned to the caller in addition to the count, to
tell the caller whether or not the block fell off the end, but
where would we put it? We can't make it a local variable in
countBeforeFred because the block can only use final
variables. Perhaps we could use a ThreadLocal. We could
put a length-one final boolean array in the local scope of
countBeforeFred, and keep the boolean value in element
zero.

If the body of the countBeforeFred were much more
complicated in its control structure at all, for example
containing a break from inside the block to outside it, this kind
of refactoring might become prohibitively complex. Realistically,
we would just give up and stop trying to use withLock at
all, effectively inling it. After all, it is only a few lines of
locking code, and it's an idiom that programmers should be
expected to learn, right? The idiom is even documented in the
javadoc of the Lock interface.

We've only touched the surface, though. The method
withLock is perhaps simple enough that you won't mind
having to inline it except in the simplest of circumstances when
it does you the least good. You might feel some discomfort at
repeating code, especially such boilerplate code, but there really
isn't any good alternative, and after all it really isn't that
much code.

However, some synchronous APIs are naturally more complex, and
it doesn't take much more complexity in the API before it simply
doesn't make sense for the caller to repeat code from the
implementation of the API to avoid these problems. Consider, for
example, an API that automatically closes your streams for you.
Instead of writing

You would write an invocation of a library method closeAtEnd to
get the same effect:

{
closeAtEnd(Stream s : openStream()) {
yourCodeHere();
}
}

You would probably go to much greater lengths to avoid inlining
the API method closeAtEnd than withLock, but the
same problems are are unavoidable. These are just two specific
examples of particular APIs of the synchronous closure variety; if
the API implementation is much more complicated, or contains
details in its implementation that callers should not be aware of,
the problem becomes acute because by-hand inlining is no longer an
option. If you've ever used
java.security.AccessController.doPrivileged, for example,
you know the pain.

While we've shown how to achieve exception transparency, we
haven't quite achieved control transparency, which means
that control constructs like break, continue,
and return have the same meaning when enclosed by a
closure. The idea is that you should be able to wrap a block of
code in an invocation of withLock, closeAtEnd,
or any other API that takes a block of code, and the meaning of
the control constructs appearing in that code should be the same.
Ideally, the only difference is that the block is executed while a
lock is held, or a stream is closed after the block, or more
generally whatever is specified and implemented by the API. You
should be able to break from the block to get out of a
loop or switch statement that might enclose the invocation of
withLock or closeAtEnd. We've looked at
examples where return is problematic, but the same
problems occur for other control constructs. Similarly, and for
the same reasons, in synchronous APIs you want to be able to refer
to and modify local variables in the enclosing scope; because the
block is executed synchronously and by the same thread, there are
no more concurrency issues than there are for an ordinary block
statement.

If you believe that these two methods - closeAtEnd and
withLock - are the only synchronous APIs worth having,
now or ever, you might be tempted to add some very specific
language features to Java to get precisely the desired
functionality, and dismiss the rest of our closure proposal. We
believe that would be a mistake, because we believe that
synchronous closures would greatly simplify the lives of
programmers. There are not many APIs of this sort today, mainly
because they can't be made to work very well with the language in
its current state.

The problem to be solved for synchronous closures is that the
programmer should not have to transform or contort his code at all
in order to wrap it in a closure to pass it to one of these APIs.

Bridging the Chasm

We're left with two seemingly irreconcilable sets of
requirements. Asynchronous closures should not be allowed to
refer to local variables in the enclosing scope, do not support
nonlocal control-flow, do not require exception transparency, and
generally speaking are done today using interfaces or abstract
classes. Synchronous closures, on the other hand, should be
allowed to refer to locals in enclosing scopes, should support
nonlocal control-flow, and may require exception transparency, but
generally speaking don't appear in the Java APIs because they are
not expressible. These use cases would seem to have so little in
common that one might not expect a single language construct to
satisfy both sets of requirements. But we believe a small
modification to the currently published proposal, in addition to the
change described in my previous blog post, satisfies both
sets of requirements. This is a very tidy result, because having
a single uniform language feature is very much preferable to
having two.

The change is very simple, but the change is not to the
specification of function types or closure expressions, it is to
the specification of the closure conversion, which allows
you to write a closure - a block of code - where a one-method
interface is expected. We add the additional restrictions that a
closure to which the closure conversion is applied must not
reference any non-final local variables from enclosing scopes, and must not use
break, continue, or return to transfer
control out of the closure, or the program is in error. These are the same
restrictions you have now with anonymous inner classes.

How does this solve both sets of problems? Well, first
consider the asynchronous use cases. These are expressed using
interfaces, and therefore in order to use these APIs with the
closure syntax, the block must be subjected to the closure
conversion. Consequently, if there is any use of a nonlocal
non-final variable, the compiler must reject the program.
Similarly, the compiler must reject the program if there is
nonlocal control-flow. The things that you will be able to do are
essentially the same as what you can do today, but with a much
simpler syntax and clearer semantics.

However, APIs for the synchronous use cases have largely not
been written yet, so they can be written using the new function
types. A closure is an expression of function type, so
the closure conversion is not required, and its restrictions do
not apply. Consequently, the block is allowed to use nonlocal
non-final variables, and can use nonlocal control-flow. The block
has essentially the same meaning as it would if it were not
wrapped by a closure. In the rare cases that an existing API is
expressed using an interface but is a synchronous use case - for
example java.security.PrivilegedExceptionAction - the
library writer can write a small utility method that converts a
closure to an implementation of the interface, enabling the client
to take advantage of the full generality of the feature.
To implement withLock using closures, with full exception- and
control-transparency, the JDK authors could write this:

Once you have support for synchronous closures, however, there
are many opportunities for the addition of extremely useful APIs
to the JDK as library methods, such as withLock,
closeAtEnd, and a method that simplifies the use of
java.security.AccessController.doPrivileged. More
importantly, synchronous closures enable Java programmers - not
the JDK authors, but ordinary Java programmers - to freely refactor
and abstract over pieces of their code in simple ways that are not
currently possible for seemingly arbitrary reasons.

Refactoring

This isn't just about writing and reading programs, it is about
refactoring programs too. Your ability to factor common code by
moving it into a separate "routine" is currently limited by how
the block passed by the caller can interact with the
caller. Closures, and synchronous closures in particular, simply
remove that limit. When a program is in need of a small
refactoring, you are free to factor just the code in common,
rather than revisiting the design of the basic data structures and
organization of your application. That was the point of my post What's
the Point of Closures. Some people missed the point, and
thought the program was merely flawed from the beginning and
should have been rewritten. Yes, it was flawed, as are most
programs in the real world. Not every programmer can get
everything right the first time, or can rewrite thousands of lines
to solve a localized issue. The whole point of such examples of
refactoring is that the original program is flawed in some
way. If the program were not flawed then refactoring might
not be required. The refactorings supported by closures enable the
programmer to get everything right in the end by small refinements
to the program, step by step.

And more...

I believe that the additional expressiveness of the language
with closures will enable people to discover and use new and
powerful kinds of design patterns to organize their code in ways
not possible today, making things simple that currently seem
complex. I have some more ideas in this direction, which I'll
write about at another time when I've had more sleep.

33 comments:

A question here... "We add the additional restrictions that a closure to which the closure conversion is applied must not reference any nonlocal non-final variables, and must not use break, continue, or return to transfer control out of the closure, or the program is in error."

nonlocal nonfinal? Nonlocal means I can't use fields, right? Isn't that even more restricting than inner classes, where I can use fields of the enclosing class?

And then about closure conversion. I name closures inline-closures whenever the closure is directly given to a method as attached block. So am I right that only this inline form would be capable of being converted to implement a one method interface? Which for example would mean I can't use the same closure for more than one actionPerformed. Am I right here?

If no, than I missed important points in your blog. If yes, then this means I won't be able to make an API working on closures if at any point such interfaces are involved. and that is most likely. Or would I warp the closure in a inner class then? If I want to avoid that, I would have to use the interfaces again. And not only that, because of the usage of checked exceptions I may have to define multiple interfaces just to cover the exception cases. That is really not very appeling. And even worse.

But exceptions are a general problem. Think of an iteration method using a inline closure. Maybe I iterate over a bunch of files where I make a backup of the file, read the file as xml, transform the file, overwrite the backup, copy the backup over the old file. Naturally this means that I might have to handle some very different Exceptions. And my only possibilties now are, that I handle them all at the place they occur (inside the closures) or to wrap them in a RuntimeException and catch them later? What a method do I have in mind here you may ask. Well (sorry, the blog doesn't allow me to use the pre tag):public class IteratorHelper { public static void forLoop(List l, Runnable closure) { for (Object o: l) closure(o) }}

This method tells us the closure will not throw any checked exception. So what do I do if I want to use a closure that throws one? I need to write a new interface taking "void(Object) throws Exception"? Do I really have to overload the method 3 or 4 times to cover exceptions? The really bad thing then would be, that these overloaded methods would not be able to share the same implementation.

And if I do not use conversion - if I operate on closure types? Do I then still have to overload the method to cover the exception cases? But ok, that might be a general problem with checked Exceptions, even with inner classes.

Ah right, the non-local-returns! So you want to disallow them in case of inlined closures? I am speaking about inline closures only here, because if you get the closures from somewhere else, then it is stored in a variable before and you won't be able to make a difference between the closures. I mean the compiler can't tell us about a closure it doesn't know, so there can't be a conversion of a closure given as parameter in a method to a one-method-interface avoiding for example "return". Ok, you could make them different by giving them different types - what ever that would be. If not it means that the interface is dominant, because if I want to call a method taking an interface with one method using a closures and the closure itself comes as method parameter, then I have to use the interface type instead of any closures type to still be able to get the conversion I need.

Please, don't think I am against closures. I am using them very much in Groovy. But while Groovy is running on the JVM, it doesn't force type or exception checks. And in case of closures not even the number of parameters is checked during compile time. This is surely a nogo for Java.

But well.. it's a draft. There is maybe more time needed to get a really nice version. Not only to read in source at the point the closure is created, but also at the point the closure is used. And of course being able to write really general programs.

Thanks, Neal, for this blog. I think I begin to see the point of closures... I often write very similar code (like the typical stream-closing you mention) and it's true that it's difficult to refactor it in a shorter way (avoiding writing the same again and again).

I like the idea of having closures in JDK7, but I must admit that some parts of the syntax are a bit ugly for me, like the declaration of a closure "a_return_type (a_param_type,another_param_type) throws an_Exception" as another parameter of a method that uses a closure. It reminds me of a C function pointer declaration. Of course we need type verification, so the types and throws declaration should be declared, but I see it a bit ugly.

If we can have a somehow clearer syntax for this, it would be ideal for me, but I know it's difficult, I can't make a proposal myself now... :-(

If the "final" restriction was lifted on local varables for annonymous inner classes and type safe function references was added to Java, wouldn't that solve the vast amount of use cases that clsoures is set out to address? And this wihout changing the language much. References to functions are simpler to understand for average Java developers IMO.

What would prevent someone from trying to create a new asynchronous API that used the function type rather than an interface with a single method? Is it just assumed people creating such APIs would have to know not to do this?

Sorry, blackdrag, my wording wasn't clear. It should say "a closure to which the closure conversion is applied must not reference any non-final local variables from enclosing scopes". I fixed the wording.

You could use two closures to implement a two-method interface by writing a little helper method that takes two closures and creates an anonymous class.

As for the issues with exceptions, that is currently a limitation of interfaces that closures don't make any worse or better. To make your method exception transparent, you'll have to make the method generic and give it a type parameter for the exception, and use function types, as I showed how to do. You can't really do it correctly with interfaces. However, we'll see what we can do about that. Check back in about two weeks.

Your example is easy to code with inner classes. Put your effort into support for a more functional style of programming with a functional style collections library, with select, reject, etc., stuff like a Tuples classes, and shoter syntax, e.g.:

Howard: the point of exception transparency is that the withLock method throws precisely the set of exceptions thrown by the block of code. Your solution causes the generic Exception to be thrown, forcing the caller to catch Exception rather than just the things thrown by the block. That undermines the benefits of compile-time exception checking.

It should be possible to distinguish synch vs. asynch based on usage syntax alone. That is, if you really care to make this distinction, then allow sync to look like blocks, but don't allow async to look like blocks. There's still no need for function types. Closure conversion really should address all needs. (And how do you define semantics for function types. Or see Tom Hawtin's blog comment on the pain of JavaDoc for function types.)

In any case, thanks for bringing the discussion public even though it's created such a boiling pot. And I agree that convenient closures are very important to solid and readable code. And that it's best not to assume we make special case blocks in advance for everything.

And sorry to go on so long, but there's one more fun use case. Swing's invokeAndWait(). That is, the point is to run the code on a separate thread, but it also runs synchronously in the sense that the current thread hangs until the other thread finishes.

I could see value in the ability to express this as a block and provide flow control and exception handling. I think this use case should also be under consideration (even if it can't be solved well enough).

And on that subject, I guess I need to study people's threading concerns with non-final vars better.

Firstly, a quick thanks for having this debate in public. Its already clear that some views and opinions are being taken onboard by the group. Secondly, thanks for going back to explain Tennents Principle and to identify the two separate use cases more clearly. In fact, this post is probably the most useful yet. Rather than post a long response here, I've blogged at my blog

I think the 80:20 rule is applicable here. For 20% of the effort you can get 80% of the benifit. I.E. just stick with the closure: throwing RuntimeExceptions, exactly one Exception in throws clause, or limit it to throwing, say, up to 5 Exceptions in its throws clause. That covers virtually all cases and is easy.

However you seem to want to cover absolutely every case, even the rare and theoretical cases. In that case why not extend generic syntax so that if the last generic argument is a Throwable or something derived from Throwable then ellipses can be used like var args. E.G.

interface F< V, E extends Throwable... > { V e() throws E; }

That is a simple solution with many possible use cases and not limited to just closures.

Howard: "varargs" generics don't work because, within the generic class, there is no way to refer to the type arguments after the trailing one. If something in this space is workable, it had better be the disjunction type, but disjunction types must be severely restricted in order not to break generic type inference. I'll blog more on this topic in about two weeks.

Stephen: a closure has precisely the same meaning no matter which kind of API it is passed to. Only in one case certain things that you try to do will be rejected by the compiler, in the other case allowed.

Neal, maybe it was late, but your reply merely emphasises the point I was making. You said "a closure has precisely the same meaning no matter which kind of API it is passed to", but then contradict that with "Only in one case certain things that you try to do will be rejected by the compiler, in the other case allowed".

This dichotomy is central to my argument. The proposal currently tries to pretend that this is one nice neat language extension, but it isn't. There are two new syntaxes being added, one where one list of things are valid, and another where a different list of things are valid. The fact that they will both look similar at a glance will make it especially confusing.

In particular, consider a *user* of closures. They won't be able to tell just from readng the 'client' code as to which type it is - sync or async. And hence what change they can or can't make. And if thats not a bad language smell I don't know what is!

Stephen: the reader won't need to know what kind of use the closure is to know what the code means. If it is legal, it can mean only one thing. A reference to a variable name not defined within the closure, for example, always designates a variable by that name in a scope lexically enclosing the closure. Similarly for method names.

If the reader needs to understand more about the semantics in the context of the method being called, the reader has to refer to the documentation for the method being called. That has always been the case, and the introduction of closures wouldn't change it.

What I cannot understand is how you are going to deal with mixing synchronous and asynchronous closure usages, i.e. if the user calls f(void ()) passing a closure that mutates enclosing local state/performs nonlocal transfer, but in f some asynchronous API is called. Is it allowed to perform closure convertion on parameter closures?

Eugene: You can still keep transparency to extract variable/method; when performing the refactoring you just make the type of the variable or method parameter the interface type required by the API instead of the function type, so that the closure conversions occurs at the site where the closure is written.

Asynchronous vs. Synchronous? As a Lisp programmer, I get the distinct impression that you may have confused the functionality of closures with the functionality of macros.

Java inner classes, when accessed outer local variables are declared as final single-value arrays, have precisely the same semantic functionality as Common Lisp closures. Your Asynchronous example is the classic example of use of such closures, in Lisp and other dynamic languages, and also in Java. And yet you're stating that inner classes aren't as powerful as "closures" because they can't be used in "synchronous" cases. Call me befuddled, because Lisp closures can't be used there either.

I think you have confused closures with macros. Closures are a semantic mechanism. Macros are syntactic manipulation. You're trying to implement in functions (with your withLock() and later auto-stream-closing examples) textbook examples, in Lisp anyway, of things that can't be properly implemented with functions. And it appears you've rediscovered the gotcha without realizing the solution. These things are trivially and cleanly implemented with macro expansion. Closures don't really have much to do with it, IMHO.

Closures are a great way to handle the Visitor pattern. Many of the languages that support closures right now, don't necessarily provide any guidance on what to expect with multithreaded code. The assumption always being that they are executed synchronously.

I would even go so far as to suggest that closures should be implemented that way, and put the onus of thread safety on the person using them. If you refer to variables outside the closure, inside a particular method, you do so at your own risk if the call is being done asynchronously.

Berin: loke many other people, you misrepresent the visitor pattern. It is all about double dispatch. See the GOF book.

In any case, closures, like methods and classes and other language constructs, can be used in a single-threaded or concurrent context, and it is up the the API author to provide any guarantees about synchronization or thread safety of the API. There is no reason to tie closures to purely-concurrent or purely-sequential use cases.

Does anything prevent us from capturing a (synchroneous) closure, e.g., by storing it in a final variable and referencing that from inside an instance of an inner class?

I.e., are closures storable?

If they are, and can thereby survive the scope they are created in, when will an error happen? Immediately when the closure is invoked, or when it tries to do something that requires being synchroeous (accessing local state or doing non-local control flow operations)?

@Lasse: the specification provides that a runtime exception is thrown in this case. Fortunately, the problem is very easy to diagnose, as the closure is lexically written inside of a method that lets it escape.

@Lasse: let me be more specific. Captured variables survive - that is, their lifetime lasts as long as any code that can refer to them. The only runtime issue that can happen is when a closure attempts to return (or break or continue) from a method that is no longer running.

About Me

Neal Gafter is a Computer Programming Language Designer, Amateur Scientist and Philosopher.
He works for Microsoft on the evolution of the .NET platform languages.
He also has been known to Kibbitz on the evolution of the Java language.
Neal was granted an OpenJDK Community Innovators' Challenge award for his design and
implementation of lambda expressions for Java.
He was previously a software engineer at Google working on Google Calendar, and a senior staff engineer at Sun Microsystems,
where he co-designed and implemented the Java language features in releases 1.4 through 5.0. Neal is coauthor of
Java Puzzlers: Traps, Pitfalls, and Corner Cases (Addison Wesley, 2005). He was a member of the C++ Standards
Committee and led the development of C and C++ compilers at Sun Microsystems, Microtec Research, and Texas Instruments.
He holds a Ph.D. in computer science from the University of Rochester.