Using MethodHandles to Reconcile Closures and Stored Messages

Every new proposal to the Java language and/or the Java Virtual Machine is automatically weighted and compared with the different proposals for closures for the Java Programming Language. The current JSR292 proposal is no exception since the versatile MethodHandle introduced in JSR292 can be used both to implement a closure as well as a stored message.

The implementation of closures and stored messages within a language can be evaluated according to the principles of duality, correspondence and invokability. By doing so we find that MethodHandles have to support co/contra variance and autoboxing as well as implicit downcast/unboxing from Object.

Also, one commonly discussed reason for adding closures to Java is wrong, but I will make up for this by adding a new reason for restricted closures.

<script language='javascript' type='text/javascript'> </script>

What Are Closures?

One possible definition is: A closure is a method whose free variables have been given values by an enclosing lexical scope. With this definition, a Java programmer uses closures every day! Let us examine the following source code:
void test1(int x) { z = x*y*5; }
The variables z and y are free variables and are usually given values by the surrounding class definition like this:

class Test1 {
    int z, y;
    void test1(int x) { z = x*y*5; }
Test1 recv = new Test1();     

We say that the closure captures the values, i.e. it binds the free variables to actual storage locations. In this case, the closure is created and the capture happens, at the time of the call: recv.test1(17);

But when programmers discuss closures, this is not what they have in mind. They refer to the situation where the free variables are given values first by a stack frame and then later by the object instance.

Using the proposed BGGA syntax, the method:
{ int x ==> z = x*y*5; }
is created and invoked within the source code of the method test2 below:

class Test2 {
    int z;
    void test2(int xx) {
        int y = 2;
        { int x ==> z = x*y*5; }.invoke(xx);

Obviously, the free variable y is given its value by the local stack frame and the free variable z is given its value, as before, by the object instance. Remember that it is only when this capture occurs that the actual closure is created. Before the capture, they are simply methods with free variables, one with a name (test1) and one without a name. To differentiate between the two, I will call the former: instance-only-closure and the latter (as expected): closure.

To further analyze closures in relation to method handles I will make use of three important principles. The first two (duality and correspondence) are well known. The third (invokability) has not been described before, as far as I know.


The Object/Closure duality principle

If a closure is a first-class object then it conforms to the object/closure duality principle. As soon as a closure is a first-class object, it can be used as method arguments, return values and stored into global variables, i.e. it can escape from its lexical context.

It turns out (and this is a known, even humorous fact) that such an escaped closure (captured by stack frame) is equivalent to an object. If you introduce first-class closures that can be captured by a stack frame, then you will inevitably introduce a secondary way of constructing objects. A simple example using (almost) BGGA syntax could be:

class Test {
  int z = 0;

  void inc() {
    if (z < 100) z++;

  void dec() {
    if (z > 0) z--;

  public static void main(String[] a) 
    Test t = new Test();;

class Test {
  enum Message { inc, dec }

  static ClosureArtistic freedom explained later... New() {
    int z = 0;

    return { Message msg ==>
      switch (msg) {
        case inc : if (z < 100) z++;
        case dec : if (z > 0) z--;

  public static void main(String[] a)
    ClosureArtistic freedom explained later... t = Test.New();

Of course, the Java Virtual Machine offers no way of holding on to the stack frame after the function has finished executing. Therefore Java closures must be implemented using objects that contain the captured variables.

Symmetrically, Scheme is a language with lexical closures but no explicit object support. Therefore objects are implemented using closures in Scheme.

* Squeak(Smalltalk) uses closures for almost everything and is an outstanding example of syntactical brevity. Though the latter does not necessarily follow from the former. For example the closure: [ :x | z:=x*y*5 ] is created and invoked within the source code of the function test3 below:

test3: xx
| y |
y := 2.
[ :x | z:=x*y*5 ] value: xx.
test4: xx
| y c |
y := 2.
c := [ :x | z:=x*y*5 ].
c value: xx.

Smalltalk closures are first-class objects, ie conforms to the duality principle. In the example on the left-hand side the creation and invokation takes place without any intermediate variable. On the right-hand side, the closure is stored into a variable before it is invoked.

Smalltalk has no control flow syntax at all. The code to be executed when a boolean is true is supplied as a closure to the boolean object using the message ifTrue. Theoretically the same ifTrue method could be added to the Java Boolean object.

test5: x
| y b |
y := 2.
b := y < 10.
b ifTrue: [ z:=x*y*5 ].
void test6(int x) {
  int y = 2;
  Boolean b = (Boolean)(y < 10);
  b.ifTrue( { ==> z=x*y*5 } );

* Ruby on the other hand, has seven different ways of expressing closures. It is worth noting that the braces {} are not used for other control flow syntax. When you see them, then you know its a Ruby closure of some sort.

Ruby has closures that are first-class objects:

def test7(xx)
  y = 2
  c = proc { |x| @z=x*y*5 }

But Ruby has also closures that are not first-class objects:

def test8
   yield 1
   yield 2

test8 { |x| puts "Hello #{x}" }

When a closure is supplied to a Ruby procedure like the above example, the supplied closure is not an object. It can only be invoked using the yield keyword.

As the Ruby collection classes show, many use cases for closures do not require the closure to be an object. This is an example in Ruby of how to create a new array of strings where all strings from the original array, are appended with a given postfix:

postfix = "_end"
a = [ "a", "b" ]
b = a.collect {|x| x + postfix } 

Ruby therefore does not always conform to the duality princple.

* JavaScript makes frequent use of closures. An example in JavaScript form would be:

function test9(xx) {
  y = 2;
  c = function(x){ z = x*y*5; };

The Javascript closures are always valid objects and therefore JavaScript conforms to the object/closure duality principle. Also Javascript closures are even mutable, as any other JavaScript object. This creates another twist on the duality within Javascript as can be seen here:

function Car(name) { = name;
  this.showme = 
    function() { alert("Car1 "; }

function newCar(name) { 
  self = function() {}; = name;
  self.showme = 
    function() { alert("Car2 "; }
  return self;

function test10() { 
  a = new Car("Volvo");
  b = newCar("Saab");

The correspondence principle

Tennent's correspondence principle as applied to closures is best explained with a simple example in Squeak. In the program on the right-hand side, an arbitrary sequence of statements are wrapped within a closure that is immediately invoked. The two programs behave identically because Squeak(Smalltalk) conforms to the correspondence principle.

     Original Source Code

| x y z |
x := 10.
y := 20.
z := x+y. 
Transcript show: z.
  Transformed Source Code ver 1

| x y z |
x := 10.
[ y := 20.
  z := x+y. ] value.
Transcript show: z.

Thus the correspondence principle for closures states that if an expression or a proper sequence of statements is wrapped with a closure that is immediately invoked, then the program should still behave the same. To be proper all parentheses, braces, brackes and other paired syntactical constructs within the sequence must balance.

To be correct, Tennent did not discuss closures when he formulated the correspondence principle. He used it to analyze the relation between variable definitions and procedure parameters. A greatly simplified example would be, if your new shiny language can define variables of type int and type long but procedure parameters can only be of type int, then you have a problem! Therefore the correspondence principle litmus test for closures should also verify that the following transforms work identically to the original source.

  Transformed Source Code ver 2

| y z |
[ :x | y := 20.
  z := x+y. ] value: 10.
Transcript show: z.
  Transformed Source Code ver 3

| z |
[ :x :y | z := x+y. ]
       value:10 value:20.
Transcript show: z.

The correspondence principle seems rather straight forward, until the discourse focuses on whether other language constructs could exist in a free state and therefore be captured by a closure and given values by a lexical environment.

Typically these constructs are return/break/continue. If the language supports first-class continuations, then one way to resolve it is to view the return/break/continue as variables holding on to continuations. Then they can clearly be free, since they are variables. This is not at all unreasonable, for example Parrot uses a continuation-based calling convention where return is indeed a continuation.

I said that Squeak(Smalltalk) has no syntax for control flow. This was a simplification, it has in fact ^ to force an early return. The two examples below behave identically. This was expected since Squeak(Smalltalk) has no other control flow syntax other than closures and an early return must therefore reside inside a closure and force a return from the lexical environment. Squeak(Smalltalk) therefore conforms fully to the correspondence principle.

     Original Source Code
test11: x
| y |
y := 20.
     Transformed Source Code

test12: x
| y |
y := 20.

[ ^x+y. ] value.

For Ruby, the keyword return sometimes return from the lexical scope and sometimes simply terminate the closure itself. Paul Cantrell's walk through is excellent, and I will not repeat it here. It suffices to say is that Ruby does not always conform to the correspondence principle.

JavaScript does not fully conform to the correspondence principle either since return within a closure simply terminates the closure.

     Original Source Code
function test13(x) {
  y = 20;
  return x+y;
     Transform fails

function test13(x) {
  y = 20;
  (funtion() { return x+y; })();

The Big Closure Question Everyone Should Know The Answer To!

There are several good reasons for adding closures to Java. However before we venture into the third design principle for closures we need to re-examine one of the reasons for closures that is common, but also, unfortunately, wrong.

The fallacious argument is that if you want to improve the syntax for binding asynchronous user interface callbacks to action code, then you should add closures to your language. For example, anonymous inner classes, a limited form of closure, was added to Java 1.1 and has been used almost exclusively for this purpose ever since. Every closure proposal has therefore been evaluated on how they improve this syntax in regard to the ActionListener, but closures should not be used for this purpose.

Does Squeak(Smalltalk) (the language that has 
no other syntax than closures for control flow) 
use closures to bind asynchronous
user interface callbacks to the action code?
Click here to reveal answer!

Please read a bit from Mark Guzdial: Squeak Object Oriented Design with Multimedia Applications, Chapter 5, page 10. You will see the following code:

button := ClockButton make: 'Hours +'
         at: ((position x) @ ((position y)+100) extent: 100@50)
         for: aModel
         triggering: #addHour.

The source code creates a clock button object that when pressed will send the message #addHour to aModel. This is not a closure, I call this a stored message, aka Squeak(Smalltalk) symbol, aka c++ method pointers, aka Objective-C selector aka JSR292 MethodHandle.

This ability to bind the view to the model directly is in the Squeak(Smalltalk) universe called pluggable views/widgets. In the OpenStep universe, this is called the Target-Action paradigm. Other implementations are available in QT and GTK as signals and slots, C# delegates, etc. They all boil down to: 1) storing a receiver and a message 2) at a later time send the message to the receiver.

Why is it better to use two variables, a receiver and a stored message instead of a closure? Let us examine a very common use case. Your application creates a save button within its constructor and then wants to bind the button to the saveState method in your app. I.e. when the save button is pressed, then the saveState method is executed. To the left we do this using a closure and to the right using a stored message with the MethodHandle syntax proposed here.

class MyApp {
  Button sb;
  public MyApp() {
    sb = new Button("Save");

  public void saveState() {
class MyApp {
  Button sb;
  public MyApp() {
    sb = new Button("Save");    
    sb.onPressed(this, #saveState);

  public void saveState() {

You might say that there is not much of a difference. But it is. The closure solution carries the weight of the lexical scope, both philosophically and practically. For example in Java there will always be an extra class for each closure.

If someone prefers closures (that can capture variables located on the stack frame) for UI callbacks, then what that person is really saying is:
When the button is pressed, I really need access to the stack frame of the constructor!

This is simply wrong since we almost never need access to the constructor stack frame at the time when the button is actually pressed! You simply want the button to execute saveState in the model with no further ado.

Practically we can of course optimize closures that do not actually make use of the lexical surroundings into something more efficient. This is a perfectly valid solution as long as the language has no stored messages. But messaging is the essence of object oriented programming! This means that if you have the choice between an (optimized)closure and a receiver/stored message pair, you should choose the latter for UI callbacks since they do not carry the philosophical backpack of lexical surroundings.

Here are some more examples of how messages are stored and later sent to receiving objects in different OO languages:

  How to execute: retval := aModel calculate using a stored message.
  recv := aModel.
  msg := #calculate.
  retval := recv perform: msg. 

  How to execute: retval = aModel.calculate using a stored message.
  recv = aModel
  msg = :calculate
  retval = recv.send msg

  How to execute: retval aModel.calculate() using a stored message.
  recv = aModel
  msg = "calculate"
  retval = recv[msg]()

In fact, the designers behind FCM and BGGA have already realized that it is convenient to have syntax to refer directly to a method without any apparent reference to the current lexical scope. Both BGGA and FCM uses the word method reference for this construct.

A method reference like: MyApp#saveState() will be transformed into the closure { MyApp m ==> m.saveState() } this is identical to the stored message (aka MethodHandle) #MyApp.saveState.

The term method reference can be confusing within an OO context. Generally a message is sent to an object that decides (based on the message) which method to execute. A method reference should therefore always be non-virtual/static/non-lazy.

The Closure/Stored message invokability principle

It was not a coincidence that it was so easy to implement a stored messages using a closure. Stored messages and closures are different yet related (invokability) much in the same way that objects and closures are different and yet related (duality).

A language conforms to the invokability principle if you can:

  1. Create a closure that will send a given message to a given receiver.
  2. Create a message, that when sent to a closure, will cause the closure to be invoked.
  3. The closure invoke and the stored message send can be performed by generic code that does not know the exact type of the receiver,message,potential parameters and return value.

Invokability is necessary in the ClockButton example above to allow the use of a closure wrapping the receiver for example to curry addHour with a value (aka the InsertArgument transform). For example like this:

button := ClockButton make: 'Hours +'
         at: ((position x) @ ((position y)+100) extent: 100@50)
         for: [aModel addHour: 17]
         triggering: #value.
But the ClockButton example is only a special case of arbitrary code execution where we register a receiver,message,parameters and pass on the return value to some other code. This can be used to generate new and efficient code at runtime, without resorting to bytecode generation.

The closure-jsr-proposal says: When closures are integrated into an object-oriented type system with subtyping, the types used to represent them obey a relationship that enables them to be used quite flexibly. [...] This enables a flexibility available in untyped languages such as Scheme, Ruby, and Smalltalk and which is achieved only with extreme awkwardness in Java today.

If a language conforms to the invokability principle, then you have achieved exactly this flexibility!

Let us examine what it looks like in different OO languages.

Turn a recv/stored message pair into a closure:
closure := [ recva perform: msga ]
Turn a closure into a recv/stored message pair:

recvb  := closure
msgb := #value

Turn a recv/stored message pair into a closure:
closure = proc { recva.send msga }
Turn a closure into a recv/stored message pair:
recvb  = closure
msgb = :call

Turn a recv/stored message pair into a closure:
closure = function(){ recva[msga]() }
Turn a closure into a recv/stored message pair:
recvb = { invoke:closure }; <-- Note!
msgb = "invoke"

Since they are dynamic languages with no static typing visible in the source, therefore the variable types that hold on to the closures and the receivers/messages cannot reveal any type information.

Clearly Squeak(Smalltalk) and Ruby conform to the invokability principle. But JavaScript does not!

This can be seen in the JavaScript example above. We have to wrap the closure in a new object that has a suitable key "invoke" so that we can use that key, as a message. Obviously the ability for a closure to be invoked resides outside of the normal object properties/messages.

We can now summaries the differences between the languages when analyzed using the three principles.


Since all the languages are useful for programming, the fact that they do not all conform to all principles, does not mean that they are broken. Instead we should see this as an indication that the OO features of Ruby and JavaScript were not consistently thought through when they were designed. (If you like, please comment on other OO languages and I will update this table.)

Since we have a chance to affect how we add closures and stored messages to Java we really want to make sure that we conform as much as possible to these principles.

How to apply these principles to Java?

Assuming that we have added MethodHandles to Java. How will the MethodHandle relate to what we have discussed so far?

1) A MethodHandle is a stored message:

As already described above the, using the proposed syntax, we can easily create a stored message like this:
MethodHandle msg = #Test1.test1;
(or simply #test1 if within the scope of Test1)
and the message is sent to a receiver like this:
Test1 recv = new Test1();

(FCM and BGGA proposed: Test1#test1() to create a stored message.)

2) A MethodHandle is an instance-only-closure:

A MethodHandle can also be an instance-only-closure, since it, when bound, contains both a receiver and a message. Using the proposed syntax we can easily create an instance-only-closure (bound MethodHandle) like this:
MethodHandle c = #recv.test1;
and the closure is invoked like this:
(FCM proposed: recv#test1() to create an instance-only-closure.)

3) A MethodHandle is a closure:

Since a stack frame Java closure will always be implemented with an object, the MethodHandle instance-only-closure can be used to hold on to a created stack frame Java closure as well!
MethodHandle c = { ==> z=x+y; };

4) A MethodHandle is even a method reference:

A true method reference can currently be acquired using MethodHandles.findSpecial(...). Are there use cases for method references that would be improved with a unique Java syntax to acquire these and if so what would such a syntax look like?

One might silently reflect over if such a versatile object should have such a mundane name.


Using a MethodHandle to hold on to closures solves a violation of the duality principle in the current BGGA proposal. Admittedly, the violation lies within the human perception and not in the technical implementation.

The syntax for a closure type in the current BGGA proposal does not look like an object. In fact it looks like a piece of code. This is a serious problem for Java programmers since they expect object types to begin with an uppercase character that are then followed by lowercase characters. Using a MethodHandle as the return value from closure creation will resolve this problem.

Every closure proposal expects the compiler to be able to track the signature of the closure at compile time and proposes their own syntax for doing so. If a MethodHandle is used to hold on to a closure, then we can for example append the proposed syntactical representation of a MethodType to the MethodHandle. The exact syntax is unimportant, this is merely a thought experiment.

MethodHandle<void>() c1 = { ==> z = y*2; };
if (!c1.type().equals(#<void>())) throw new Error();

MethodHandle<void>(int) c2 = { int x ==> z = x*y; };
if (!c2.type().equals(#<void>(int))) throw new Error();

MethodHandle<double>(int,float) c3 = { int x, float y ==> (double)(x*y) };
if (!c3.type().equals(#<double>(int,float))) throw new Error();

MethodHandle<Object>(String,int) c4 = { String s, int x ==> "("+s+x+")" };
if (!c4.type().equals(#<String>(String,int))) throw new Error();

MethodHandle<String throws IOException>(Reader) c5 = { Reader r ==> r.readLine() };
if (!c5.type().equals(#<String throws IOException>(Reader))) throw new Error();

MethodHandle c6 = (MethodHandle)c5;
MethodHandle<Object>(Object) c7 = (MethodHandle<Object>(Object))c6;

MethodHandle<double restricted>() c8 = { => x*1.2 };

Instead of having a MethodHandle without any suffix, we could use something similar to
MethodHandle<?>(?...) to refer to a MethodHandle for which we have no compile time information. As long as this does not cause any (or at least not too much) cognitive dissonance in respect to normal generics.

To maintain compatibility with legacy library methods that use interfaces, it should be easy to cast a MethodHandle to any interface with a single compatible method. This can be done with only a single hidden wrapper class per interface, or even by modifying the behavior of the bytecode where we could allow (for all compatible signatures) checkcast from a MethodHandle to an interface to succeed and invokeinterface on a MethodHandle to work.

  boolean running = true;
  // Thread executing closure...
  Runnable r1 = (Runnable){ ==> while(running) { doSomething(); } };
  // Thread executing instance-only-closure...                               
  Runnable r2 = (Runnable)#this.getGoing;
  Thread t1 = new Thread(r1);
  Thread t2 = new Thread(r2);
  running = false;  


If MethodHandles are used for closures, then they must conform to Tennent's correspondence principle. Therefore it has to allow for co/contra variance in the return value/arguments. Without co/contra variance, the following transform will not even execute.

        Original Source Code
Object o;
long id;
o = "Hello";
id = (int)o.hashcode();
     Transformed Source Code

long id;
id = { Object o ==>(int)o.hashcode() }

Also a MethodHandle.invoke cannot be declared to always throw a checked Exception (as in the current proposal) since that would prevent exception transparency of the closure.


The intriguing solution to put both closures and stored messages into the same object (the MethodHandle), exercises both the duality principle and the invokability princple at the same time. Invokability within a typed source code language requires that the type systems for closures and stored messages are compatible similarly to how variables and parameters must be compatible according to the correspondence principle. Having a single object type for both closures and stored messages, solves this problem automatically. However to conform to the invokability principle we must also make sure that we can generate a closure (1), generate a message (2) and verify (3) where neither the closure, nor the receiver/message pair reveal type information.

Java (proposed syntax):
How to execute: int retval = aModel.calculate() using a stored message.
Object recva = aModel;
MethodHandle<int>(Object) msga = #MyModel.addHour.
int retval = msga.invoke<int>(recva);

Turn a recv/stored message pair into a closure with no type information:
MethodHandle<Object>() closure = { ==> msga.invoke<int>(recva) }

Turn a closure into a recv/stored message pair with no type information:
Object recvb = closure;
MethodHandle<Object>(Object) msgb = #MethodHandle<Object>().invoke

Which is again put to use:
int retval = msgb.invoke<int>(recvb);

It is not possible to conform to the invokability principle without implicit downcast from Object to the correct parameter type. The current BGGA prototype supports this. To return an untyped value that can be used further, we also need boxing and unboxing, both for parameters and the return value. The BGGA prototype does not currently support this.


Java (proposed)YesYesYes


Revisiting UI callbacks

We can now revisit the UI example above where a pair consisting of a receiver and a stored message was used to register a callback from an UI button. But such a pair is indeed an instance-only-closure (bound MethodHandle). It should therefore be possible to use a single MethodHandle as the parameter to onPressed. I.e. the declaration of onPressed is:
void onPressed(MethodHandle<void>() action) { ... }

By doing so, both the following uses of onPressed will be possible. We can use a stored message (the left hand side example), or if we need to curry the callback, we can use a closure (the right hand side example).

class MyApp {
  Button sb;
  public MyApp() {
    sb = new Button("Save");    

  public void saveState() {
class MyApp {
  Button sb;
  public MyApp() {
    sb = new Button("Save");

  public void saveStateN(int n) {

Closures as a resource for dynamic language runtime developers

If closures are MethodHandles, then it is possible to create the java.dyn transforms with more syntactical brevity since we can use the restricted closure to our advantage!

The optimizer can inline invokations on MethodHandles as soon as the MethodHandle variable is final and bound. (It can inline non-final MethodHandles as well, but then it will need to profile the execution first.) Since all variables captured by a restricted closure are final this will guarantee that the invoked target will be inlined quickly.

For example, if you have the invokedynamic call site:


then you can in the boostrap, create an add argument transform on the fly:

callsite.setTarget( { int x => target.invoke<int>(100, x) } );

The target variable will be final within the restricted closure and can therefore easily be inlined. If we revisit the different implementations of MethodHandle transforms, here an appendArgument transform. We can see that the implementation of the transforms can be even shorter with the help of closures.

For JVMs that cannot optimize varargs constant arraycopys, this implementation is suitable: For JVMs that can optimize varargs and constant arraycopys, this implementation is very short:
appendArgument(MethodHandle<?>(?...) target,
               Object arg)
 switch (target.numArguments()) {
    case 1 :
      return { => target(arg) };
    case 2 :
      return { Object a =>
    case 3 :
      return { Object a, Object b =>
    . (continue to 20)
  throw new CantDoThat();
appendArgument(MethodHandle<?>(?...) t,
               Object arg)
    target =;
    { Object[] in
      Object[] out = new Object[in.length+1];

      out[in.length] = arg;


MethodHandles are on their way into Java. If we make sure that they can be used both for closures and stored messages then they will contribute significantly to the Java language itself.

Fredrik Öhrström


  1. Closures for the Java Programming Language (BGGA)
  2. Concise Instance Creation Expressions (CICE)
  3. Clear, Consistent, and Concise Syntax (C3S) for Java
  4. First Class Methods (FCM)
  5. Closures And Objects Are Equivalent
  6. Brian Goetz: Java theory and practice: The closures debate
  7. Klaus Kreft and Angelika Langer: Understanding the closure debate
  8. Alex Blewitt: When is a closure not a closure?
  9. Abelson & Sussman: Structure and Interpretation of Computer Programs
  10. Mark Guzdial: Squeak Object Oriented Design with Multimedia Applications, Chapter 5
  11. Steve Burbeck: Applications Programming in Smalltalk-80(TM)
  12. Alan Kay: Messaging is more important than Objects
  13. John Rose: Better Closures
  14. John Rose: Closures without Function Types
  15. Rémi Forax: Closures with Function Types
  16. Rémi Forax: Closure Literal and Method Reference
  17. Neal Gafter: Tennents Correspondence Principle
  18. Neal Gafter: A Presentation of BGGA Closures
  19. Neal Gafter: Use cases for closures
  20. Zdeněk Troníček: Method references (version 2008-03-17)
  21. Stephen Colebourne: Comparison of BGGA, CICE, FCM
  22. Howard Lovatt : Comparing Inner Class/Closure Proposals (C3S,FCM,CICE,BGGA)
  23. Howard Lovatt : An Alternative to Closure Conversion and to Restricted Closures
  24. Elliotte Rusty Harold: Homework for Closures
  25. Douglas Crockford: Tennent's correspondence principle.
  26. Thread discussing Tennent's correspondence principle

ActionListeners are not a valid reason for closures
Though it is of course important to be backwards-compatible with ActionListeners.


Post a Comment:
Comments are closed for this entry.



« June 2016