First-class methods: Java-style closures

Version 0.5


Stephen Colebourne, UK
Stefan Schulz, Germany

I. Problem

In Java, the method is the principal construct where application logic resides. At present, a method can only exist within a class and cannot be manipulated or referenced in any simple manner. Other languages permit a block of application logic to be referenced outside of a class, and this is often referred to as a function or a closure.


A Java developer can approach the power of functions/closures using two techniques - reflection [5] and inner classes [1:15.9]. However, neither is very developer friendly - reflection is not compile-time safe or refactorable, and inner classes are very verbose.


As a result of the difficulty of writing code using reflection and inner classes the techniques tend to be limited to callbacks between an application and a framework. However, the majority of uses of functions or closures in other languages is for small-scale code re-use. This typically involves refactoring out common sections of code which may have a common beginning and end, but different code in the middle. In this scenario, the extracted code isn't run at a much later time like a callback is, but immediately as the original code would have done.


To enable this power in Java, we propose to change the language to support the referencing and definition of methods as first-class objects. This provides much of the power of functions/closures but in a style familiar to Java developers.


We further propose to enable the referencing of other class members - constructors and fields - as first-class citizens. This is a natural extension to First-class Methods.


Sorting example

The Comparator interface is the standard mechanism in Java to provide the code needed to sort lists. Here is a Comparator that sorts by length of String:

  List<String> list = ...
  Collections.sort(list, new Comparator<String>() {
    public int compare(String str1, String str2) {
      return str1.length() - str2.length();
    }
  });

With the changes in this proposal, the code could be written as follows:

  List<String> list = ...
  Collections.sort(list, #(String str1, String str2) {
    return str1.length() - str2.length();
  });

This syntax is termed an anonymous inner method, and is a logical extension to the anonymous inner class concept. The conversion to a Comparator is automatic.

Event listener example


The Swing GUI framework makes widespread use of listeners to inform the application of events. These are frequently implemented as inner classes which delegate their behaviour to a 'normal' method on the class initialising the listener:

  public void init() {
    JButton button = ...;
    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent ev) {
        handleAction(ev);
      }
    });
  }
  public void handleAction(ActionEvent ev) {
    // handle event
  }

With the changes in this proposal, the code could be written as follows:

  public void init() {
    JButton button = ...;
    button.addActionListener(this#handleAction(ActionEvent));
  }
  public void handleAction(ActionEvent ev) {
    // handle event
  }

This syntax uses a bound method reference to refer to a pre-existing method on a specific object. The conversion to an ActionListener is automatic.

II. Member literals

Member literals represent a literal form, similar to double quoted Strings, for referring to a class's members. There are three kinds of literals each referring to the respective type of member: method literals (1), constructor literals (2), and field literals (3).


MemberLiteral:

    MethodLiteral

    ConstructorLiteral

    FieldLiteral


All kinds of member literals follow the standard rules for visibility. A member literal may refer to a public member from anywhere, to a protected member only from subclasses and within the same package, to a default scope member from within the same package, and to a private member only from within that class.

1. Method literals

A method literal refers to a method definition. The syntax consists of the class name, followed by the # (hash) symbol and the method name with parameter types.


Rationale: The use of the # symbol is deliberate. The symbol is already used within Javadoc to separate the class name from the method name in exactly this manner. The method literal syntax merely brings the Javadoc convention into Java source code.
We go on to use the same # symbol throughout the proposal for method related syntaxes, helping to provide consistency.


Examples

The following examples refer to static methods:

  Math#min(int, int)
  Collections#sort(List, Comparator)

The following examples refer to instance methods:

  Integer#intValue()
  Object#equals(Object)

Detail

Method literals are, by definition, assignable to java.lang.reflect.Method. As such, it is possible to call any part of the API of Method directly:

  Class<?> returnType = Integer#intValue().getReturnType();

This calls the getReturnType method on the Method object contextually created by the method literal.


Syntax

MethodLiteral:

    ClassType # Identifier ( TypeListopt )

2. Constructor literals

A constructor literal refers to a constructor definition. The syntax consists of the class name, followed by the # (hash) symbol and the constructor's parameter types.

Examples


  ArrayList#(int)
  JButton#(String, Icon)

Detail

Constructor literals are by definition assignable to java.lang.reflect.Constructor<T>, where T must be assignable from the referred class.

It is a compile-time error to reference an abstract class' constructor.

Syntax

ConstructorLiteral:
    ClassType # ( TypeListopt )

3. Field literals

A field literal refers to a field definition. The syntax consists of the class name, followed by the # (hash) symbol and the field's name.

Examples

The following examples refer to static fields:

  Member#DECLARED
  Node#ELEMENT_NODE

The following examples refer to instance fields:

  MyBean#name
  TaskEntry#priority

Detail

Field literals are by definition assignable to java.lang.reflect.Field.

Syntax

FieldLiteral:
    ClassType # Identifier

III. Method types

Method types are a way to define the signature of a method or block of code. As such, they must define the parameters, return type, and thrown exceptions.

The syntax consists of the # (hash) symbol followed by parentheses. Within the parentheses the method signature is specified following the logical order of defining a method - the return type, followed by the parameter types in parentheses, followed by any exceptions.

Rationale: The use of the # symbol provides a clear visual indication to the developer as to the start of the method type. We feel that using # is considerably clearer in use than the alternatives we examined, including using braces (curly brackets) and a Haskell like notation [2].
The order and style of the method type is very deliberately following that of a method declaration in Java. This is to allow developers to pickup the new syntax easily.

Examples

The following examples show various forms of method types, with various return types, parameters, and thrown exceptions:

  #(int(String, String))

  #(void(String))

  #(String(File) throws IOException)

  #(long())


The following example shows how a method type can be assigned to an ActionListener interface:

  #(void(ActionEvent)) method = ...
  ActionListener lnr = method;


This will compile to code equivalent to:

  static class Outer$MethodType$1 implements ActionListener {
    private final #(void(ActionEvent)) target;
    public
Outer$MethodType$1(#(void(ActionEvent)) target) {
      this.target = target;
    }
    public void actionPerformed(ActionEvent arg1) {
      target.invoke(arg1);
    }
  };
  #(void(ActionEvent)) method = ...
  ActionListener im = new Outer$MethodType$1(method);

Detail

An instance of a method type supports a single method, invoke, that can be used to call the method. Both the arguments and the return type of the invoke method are fully type-safe. For example:

  #(boolean(String,String)) nullSafeEqualsMethod = ...
  boolean equal = nullSafeE
qualsMethod.invoke("Hello", "Hi");


Method types will be implemented as a compiler-generated interface. Considerable investigation and study of the implementation of this concept has already been undertaken as part of the BGGA proposal [4] (function types). As such, we don't attempt to duplicate that work here.


A method type may be assigned to a class or interface provided that the compiler-generated class has a single abstract method with a fully compatible signature. It is a compile error if there is zero or more than one abstract method.

Syntax

Type:

    MethodType


MethodType:

    # ( ResultType ( TypeListopt ) Throwsopt )  


IV. Method references

Method references are a way to refer to a specific method and its environment such that it can be invoked. There are four kinds of method references: static method reference (A1), instance method references (A2), bound method references (A3) and constructor references (A4). They share a common auto-conversion mechanism for assigning a method reference to a class or interface (B).

MethodReference:

    StaticMethodReference

    InstanceMethodReference

    BoundMethodReference

    ConstructorReference

A1. Static method references

A static method reference provides a type-safe way to obtain an object that can be used to invoke a static method.

The syntax consists of the class name, followed by the # (hash) symbol and the static method name with parameter types.

Examples

The following example shows the method type to which a static method reference can be assigned:

 
#(int(int, int)) ref = Math#min(int, int);

This will compile to code equivalent to:

  static class Outer$StaticMethodReference$1 implements #(int(int, int)) {
    public int invoke(int arg1, int arg2) {
      return Math.min(arg1, arg2);
    }
  };
  #(int(int, int)) ref = new Outer$StaticMethodReference$1();

Detail

A static method reference has the same syntax form as a method literal. It becomes a method reference when it is assigned to, or passed to, a method type.

At compilation time, the static method reference will be implemented by a compiler-generated class. The class will implement the method type that the reference is assigned to.

Syntax

StaticMethodReference:

    ClassType # Identifier ( TypeListopt )

A2. Instance method references

An instance method reference provides a type-safe way to obtain an object that can be used to invoke an instance method. An instance method must be invoked on an object, so the reference is adjusted to pass the object as the first parameter.

The syntax consists of the class name, followed by the # (hash) symbol and the instance method name with parameter types.

Examples

The following example shows the method type to which an instance method reference can be assigned. Note how the method type takes an additional parameter which is the object that will be invoked:

 
#(int(List, Object)) ref = List#indexOf(Object);

This will compile to code equivalent to:

  static class Outer$InstanceMethodReference$1 implements #(int(List, Object)) {
    public int invoke(List arg1, Object arg2) {
      return arg1.indexOf(arg2);
    }
  };
  #(int(List, Object)) ref = new Outer$InstanceMethodReference$1();

Detail

An instance method reference provides a bridge between object-oriented programming and procedural programming. It is the equivalent of turning an instance method into a static method, by passing the instance to be invoked as the first argument.

An instance method reference has the same syntax form as a method literal. It becomes a method reference when it is assigned to, or passed to, a method type.

At compilation time, the instance method reference will be implemented by a compiler-generated class. The class will implement the method type that the reference is assigned to.

Syntax

InstanceMethodReference:

    ClassType # Identifier ( TypeListopt )

A3. Bound method references

A bound method reference provides a type-safe way to obtain an object that can be used to invoke an instance method. To achieve this, it captures the object that it is to be invoked on.

The syntax consists of an expression yielding an object, followed by the # (hash) symbol and the method name with parameter types.

Examples

The following example shows the method type to which a static method reference can be assigned:

  List<String> list = ...
 
#(int(Object)) ref = list#indexOf(Object);

This will compile to code equivalent to:

  static class Outer$BoundMethodReference$1<T> implements #(int(Object)) {
    private final List<T> target;
    public
Outer$BoundMethodReference$1(List<T> target) {
      this.target = target;
    }
    public int invoke(Object arg1) {
      return target.indexOf(arg1);
    }
  };
  List<String> list = ...
  #(int(Object)) ref = new Outer$BoundMethodReference$1<String>(target);

Detail

A bound method reference is more complex than a static or instance method reference because it captures the object that it is invoked on. This capturing provides a very quick and easy way to pass a callback to a framework.

At compilation time, the bound method reference will be implemented by a compiler-generated class which stores the target object as an instance variable. The class will implement the method type that the reference is assigned to.

Syntax

BoundMethodReference:

    Primary # Identifier ( TypeListopt )

A4. Constructor references

A constructor reference provides a type-safe way to obtain an object that can be used to invoke a constructor.

The syntax consists of the class name, followed by the # (hash) symbol and the parameter types.

Examples

The following example shows the method type to which a constructor reference can be assigned:

 
#(Integer(int)) ref = Integer#(int);

This will compile to code equivalent to:

  static class Outer$ConstructorReference$1 implements #(Integer(int)) {
    public Integer invoke(int arg1) {
      return new Integer(arg1);
    }
  };
  #(Integer(int)) ref = new Outer$ConstructorReference$1();

Detail

A constructor reference has the same syntax form as a constructor literal. It becomes a constructor reference when it is assigned to, or passed to, a method type.

At compilation time, the constructor reference will be implemented by a compiler-generated class. The class will implement the method type that the reference is assigned to.

Syntax

ConstructorReference:

    ClassType # ( TypeListopt )


B. Common rules and mechanisms

Conversion to class or interface

 
A method reference of any of the four kinds may be assigned to a class or interface providing that the compiler-generated class has a single abstract method with a fully compatible signature. It is a compile error if there is zero or more than one abstract method.

The following example on a bound method reference creates a compiler-generated class implementing ActionListener where the single abstract method actionPerformed calls the handleAction method on this.

  ActionListener lnr = this#handleAction(ActionEvent ev);

This assignment will be compiled to code equivalent to:

  static class Outer$InstanceReference$1 implements ActionListener {
    private final Outer target;
    public
Outer$BoundMethodReference$1(Outer target) {
      this.target = target;
    }
    public void actionPerformed(ActionEvent arg1) {
      return target.handleAction(arg1);
    }
  };
  ActionListener lnr = new Outer$InstanceReference$1(this);

If the method handleAction is not accessible for any reason, a synthetic method will be generated by the compiler.

The example on a constructor reference below creates a compiler-generated class implementing ViewFactory where the single abstract method create invokes the constructor on IconView.

  ViewFactory vf = IconView#(Element);

This assignment will be compiled to code equivalent to:

  static class Outer$ConstructorReference$1 implements ViewFactory {
    public View create(Element arg1) {
      return new IconView(arg1);
    }
  };
  ViewFactory vf = new Outer$ConstructorReference$1();

V. Inner methods

Inner methods are a way of writing a method in-line within the body of another method. This is analogous to an inner class but for methods. There are two kinds of inner method: anonymous (A1) and named (A2). Both of which share some common rules and mechanisms (B).

InnerMethod:

    AnonymousInnerMethod

    NamedInnerMethod

A1. Anonymous inner methods

An anonymous inner method is a method written within the body of another method. It has no name and may be assigned to a method type or a class/interface with a single abstract method.

Examples

The following example creates an anonymous inner method assigned to a method type:

  #(void(ActionEvent)) action = #(ActionEvent ev) {
    System.out.println("ActionEvent fired");
  }

This will compile to code equivalent to:

  static class Outer$InnerMethod$1 implements #(void(ActionEvent)) {
    public void invoke(ActionEvent arg1) {
      System.out.println("ActionEvent fired");
    }
  };
  #(void(ActionEvent)) im = new Outer$InnerMethod$1();


The following related example creates an anonymous inner method assigned to a single abstract method interface:

  ActionListener action = #(ActionEvent ev) {
    System.out.println("ActionEvent fired");
  }

This will compile to code equivalent to:

  static class Outer$InnerMethod$1 implements ActionListener {
    public void actionPerformed(ActionEvent arg1) {
      System.out.println("ActionEvent fired");
    }
  };
  ActionListener im = new Outer$InnerMethod$1();

Detail

An anonymous inner method may be assigned to a matching method type or a single abstract method type.

At compilation time, the anonymous inner method will be implemented as a method on a compiler-generated class. The class generated depends on the context to which the inner method is assigned:


It is a compiler error to declare an anonymous inner method without a context type. It is also a compile error, if there is zero or more than one abstract method on the context class/interface.

Syntax

AnonymousInnerMethod:
    # InnerMethodParametersopt Block

InnerMethodParameters:
   
( FormalParameterListopt )

A2. Named inner methods

A named inner method is a method written within the body of another method that has a name associated with it.

Examples

The following example creates a named inner method assigned to a ThreadLocal with the aim of initialising the object correctly:

  private final AtomicInteger nextId = new AtomicInteger(0);
  private final ThreadLocal<Integer> threadId = #initialValue() {
    return nextId.getAndIncrement();
  };

This will compile to code equivalent to:

  static class Outer$InnerMethod$1 extends ThreadLocal<Integer> {
    public Integer initialValue() {
      return nextId.getAndIncrement();
    }
  };
  ThreadLocal<Integer> threadId = new Outer$InnerMethod$1();

Detail

A named inner method may be assigned to a matching method type or the majority of other types. The name is used to determine which method will be overridden.

At compilation time, the named inner method will be implemented as a method on a compiler-generated class. The class generated depends on the context to which the inner method is assigned.



Rationale: Previous versions of FCM proposed implementing abstract methods that were not overridden with empty stubs. After consideration, it was decided that this is too risky, and has been removed. As a result, the 'method compound' concept from v0.4 has also been removed. Thus you cannot implement MouseListener using FCM - for that you need an inner class.

It is a compiler error to declare a named inner method without a context type.

Syntax

NamedInnerMethod:
    # Identifier InnerMethodParametersopt Block

B. Common rules and mechanisms

The content of inner methods has the following rules:


These rules are similar to those of inner class methods with two exceptions, the this keyword and local variables.

Rationale: These rules are at the heart of what differentiates one closure proposal from another. The CICE proposal [3] provides a means to simplify the creation of inner classes. The complex semantics of this remain. The BGGA proposal [4] takes the opposite route and tries to remove all restrictions on the content of the block. This results in a different set of issues, such as using exceptions for control flow and the RestrictedFunction interface which considerably changes the allowed content of the block.

The use of the keyword return to return a value from the inner method is driven by a desire to stay close to the existing Java syntax for methods. The BGGA proposal [4] uses the concept of last-line-no semicolon to return a value from a closure. We consider that error-prone, inflexible (as it doesn't allow early return) and unlike any other part of Java syntax.

See the semantic choices section for more detail.

Accessing this

The this keyword applies to the nearest enclosing class within the source code. (i.e., it does not apply to the compiler-generated class that is created to hold the method when implemented.) The reason for this is simple - as far as the developer is concerned there is no visible class in the source code for this to refer to.

In the following (contrived) example, the log method is called using this. The object that will be passed to the log method is the instance of MyClass that surrounds the inner method.

  public class MyClass {
    public void process() {
      #(void(String)) example = #(String message) {
        Logger.log(this, message);
      };
      example.invoke("Logged message");
    }
  }

Accessing local variables

Local variables in the enclosing scope will be fully accessible to the inner method. If the local variable has been declared final, then it will be read-only. Otherwise, it will be read-write. The conversion to allow local variables to be accessed from two places will occur at compile-time.

The method that receives an inner method may run concurrently with the method that created the inner method. This might cause a race condition with any shared local variables. We propose an annotation, @ConcurrentLocalVariableAccess, that applies to the method parameter which receives the inner method. This can be used to act as a warning to the compiler and development environments to help avoid race conditions.

Rationale: These rules for accessing local variables are the least restrictive possible. Any local variable may be accessed by any inner method. To avoid our previous concerns with race conditions we propose an annotation, used to provide warnings and development environment support.

See the semantic choices section for more detail.


Syntax when no parameters

For an inner method not having parameters the parentheses may be omitted:

  #{ ... }
  #methodName{ ... }


Rationale:
The no argument case is fairly common, and the syntax looks considerably more appealing with the parentheses removed.

Transparency

When an inner method is invoked immediately (synchronously) by the higher order method that it is passed to, it can be useful to handle exceptions more fully. What is required, is that any checked exception that could be thrown by a statement in the inner method block is transparently made to be an exception of the higher order method.

The BGGA proposal [4] provides mechanisms to achieve this, and we reference that work here.

VI. Further examples

The following sections present some application scenarios for the proposed language enhancements.

Executor


The executor part of the concurrency framework allows a task to be submitted to run in another thread. This is typically written as an inner class at present:

  Executor exec = ...;
  exec.execute(new Runnable() {
    public void run() {
      // code to run in another thread
    }
  });

With the changes in this proposal, the code could be written as an anonymous inner method as follows:

  Executor exec = ...;
  exec.execute(#{
    // code to run in another thread
  });

ThreadLocal initialization


The ThreadLocal class provides a protected method to allow easy initialization. This is intended to be used as an inner class at present:

  private static final AtomicInteger nextId = new AtomicInteger(0);
  private static final ThreadLocal<Integer> threadId = new ThreadLocal<Integer>() {
    @Override
    protected Integer initialValue() {
      return nextId.getAndIncrement();
    }
  };

With the changes in this proposal, the code could be written as a named inner method as follows:

  private static final AtomicInteger nextId = new AtomicInteger(0);
  private static final ThreadLocal<Integer> threadId = #initialValue() {
    return nextId.getAndIncrement();
  };
 
Inner loop example

Java's collection framework provides the mechanism of iterators to loop on a collection's entries outside the collection. A common code pattern to find a matching entry looks like follows:

  PersonCache personCache = ...
  Person found = null;
  for (Person person :
personCache.getPersonList()) {
    if (person.getAge() >= 18) {
      found = person;
      break;
    }
  }

With the changes in this proposal, a method could be provided directly by the domain model, e.g., PersonCache allowing the code to be written as follows:

  PersonCache personCache = ...
  Person found = personCache.find(#(Person person) {
    return person.getAge() >= 18;
  });


This syntax uses an anonymous inner method to return a boolean true or false value. The inner method is called for each Person until the match is found and the inner method returns true.

VII. Open issues

  1. Is a widening conversion reasonable, either in general or on SAM types, e.g. for eliding unused parameters
  2. API to handle method types
  3. Is there a shortcut syntax to avoid specifying the types in a method literal or invocable method reference when the method is not overloaded, for example Object#equals(...)
  4. Field references (any discussion on property references are out of scope for this document)
  5. Is there a way to add support for currying and recursiveness from inner methods

Semantic choices

This section is Rationale about our semantic choices.

In discussing this proposal we identified three basic use-cases - asynchronous (callbacks, like swing event listeners), synchronous (inline code refactoring, like sorting) and control abstraction (keyword based, like withLock or usingFile). The way in which each 'closure' proposal handles these cases is key to understanding their differences.

With FCM we have, after much consideration, decided that the asynchronous and synchronous use cases do not truly differ in semantics. The control abstraction use case differs significantly however.

With both the asynchronous and synchronous use case, an application developer can create an instance via an inner method and assign it to a local variable. The normal case is that the local variable is then passed to a method as a parameter (either an asynchronous or synchronous use case method). The local variable holding the inner method then falls out of scope at the end of the method it is defined in:

  public Person findPerson(PersonCache cache) {
    #(boolean(Person)) matcher = #(Person person) {...};
    return cache.find(matcher);
  }


In the example above, the matcher is being used synchronously - the matcher is created and used inline within a single method. However, it is possible to refactor the code slightly:

  public Person findPerson(PersonCache cache) {
    #(boolean(Person)) matcher = createMatcher();
    return cache.find(matcher);
  }

  public #(boolean(Person)) createMatcher() {
    return #(Person person) {...};
  }


Now, the matcher is being created in one method, and used in another. Is this still a synchronous use case? Or an asynchronous one? Somewhere in between? The reality is that both use cases end up operating in the same way. Both are an inner method that can be assigned to a variable and passed around as per any other variable.

This implies that using continue or break keywords within the inner method to refer to the method defining the inner method is meaningless. This is because the method defining the inner method and any loop may have been completed before the inner method is invoked. The same logic holds for using the return keyword to return from the enclosing method. As a result, FCM does not permit continue or break from within the inner method, and uses return to return a value from the inner method.

We did have a concern that the asynchronous use case might get into a race condition over local variables, so in FCM v0.4 we restricted local variable access to read-only. However, the synchronous use case requires full read-write access to local variables. As a result FCM v0.5 allows full read-write access to local variables, and provides an annotation to warn if there may be concurrent access to local variables, which is where the real danger of race conditions lies.

The final point of consideration was the control abstraction syntax. We established that the control abstraction use case is very different from the other use cases.

  public void process() {
    Lock lock = ...
    withLock(lock) {
      // code protected by the lock
    }
  }


This example is at face value similar to the synchronous use case - the block of code is executed immediately and inline. However, there is a key difference - the block of code cannot be assigned to a variable within the process method. As a result, there is no way to pass the block of code to another method in the application - the block is fixed at this point in the code.

A result of being fixed at this point in the code is that the semantics of the block are entirely different to blocks which can be assigned to a variable. The continue and break keywords should refer to the nearest loop, while the return keyword should refer to the enclosing method. In other words, it has the full semantics of a normal Java block. Implementing a mechanism to handle control abstraction is thus outside the scope of FCM.

Syntax choices

This section is Rationale about our syntax choices.


When writing a proposal like FCM, there are two aspects to consider - syntax and semantics. Semantics is by far the most important, as it describes what happens in each scenario, and is the guts of the proposed change. However, it is almost always necessary to show examples, and for that you need to use a syntax.


With FCM, we chose to use the # symbol as our key syntactic element. There were a number of reasons. Firstly, # is unused in Java at present. This means that there are no conflicts within the parser, simplifying the proposal. It also means that someone reading the resulting code doesn't have to think about what the symbol means (unlike ?, <, > or : for example). The # has been used by Java developers before however, as it is used in Javadoc.

It has been pointed out that in most, if not all, cases, the parser could work out the meaning of the code without the use of the symbol at all. This is true, but a key feature of Java is readability. We believe that in this case, the extra symbol adds to the readability by clearly identifying the method syntax. This is important for inner methods which are likely to be running in another thread, hence the # acts as a kind of warning.

Our decision on the method type syntax took quite a bit of thought. We chose a syntax which followed the layout of a Java method declaration - return type, then arguments in brackets, then any exceptions. We did consider a number of alternatives. For example, this is one alternate method type syntax that has some appeal (using the examples from the method types section):

  #(String, String return int)

  #(String)

  #(File return String throws IOException)

  #(return long)


The last goal for our syntax was to be unambiguous. We didn't want to introduce any new elements of name shadowing.

Finally, it should be borne in mind that the syntax is relatively unimportant - the semantics of the proposal are what really matter.

Acknowledgments

This proposal is based on the great work of the BGGA and CICE closure proposals.

Our thanks go to Ricky Clarkson for acting as technical reviewer.

In addition, the authors wish to thank all who contribute to the lively Java blog and forum community.


Notes


Changes from v0.4


References

  1. The Java Language Specification, Third Edition

    http://java.sun.com/docs/books/jls/third_edition/html/j3TOC.html
  2. The Haskell 98 Reports, Expressions, Section: 3.3 Curried Applications and Lambda Abstractions

    http://haskell.org/onlinereport/exps.html#sect3.3
  3. B. Lee, D. Lea, J. Bloch: "Concise Instance Creation Expressions: Closures without Complexity"
    http://docs.google.com/Doc.aspx?id=k73_1ggr36h
  4. G. Bracha, N. Gafter, J. Gosling, P. von der Ahé: "Closures for the Java Programming Language  (v0.5)"

    http://www.javac.info
  5. Java™ Platform Standard Ed. 6, Reflection API
    http://java.sun.com/javase/6/docs/api/index.html?java/lang/reflect/package-summary.html

  6. R. D. Tennent: "Principles of Programming Languages"
    Prentice Hall International,
    Englewood Cliffs, NJ, USA, 1981