Friday, December 28, 2007

Closures

Closures

A closure is a form of anonymous function. It is declared using the following syntax:
{ formal parameters => statements expression }. Formal parameters, statements, and expression are optional in this clause. For example, { int x => x + 1 } is a function that takes a single int argument and returns its value incremented by 1. A closure can be invoked by the invoke method. For example, { int x => x + 1 }.invoke(10) will call the closure with argument 10.

  public class SimpleClosure {
  
    public static void main(String[] args) {
      // function with no arguments; return value is always 42
      int answer = { => 42 }.invoke();
      System.out.println(answer);
    }
  
  }
  

A closure with one argument:

  double log = { double x => Math.log(x) }.invoke(10);
  

A closure with a statement:

  // this will print "31 is odd" and return 15
  int half = { 
    int x => 
    if (x % 2 != 0) System.out.printf("%d is odd%n", x); x / 2
  }.invoke(31);
  

A closure with two arguments:

  int sum = { int x, int y => x + y }.invoke(3, 4);  // will return 7
  

A closure does not have to return any value (the function may have return type void):

  { char c => System.out.println(c); }.invoke('@');  // will print @
  

A closure that returns a string:

  String reversed = { 
    String s => 
    new StringBuilder(s).reverse().toString()
  }.invoke("abcd");  // will return "dcba"
  

A closure that returns an instance of Runnable.

  { => new Runnable() {
      public void run() {
        System.out.println("hi from Prague");
      }
    }
  }.invoke().run();  // invoke() returns an instance of Runnable and we 
                     // call run() on it immediately
  

We can declare local variables in closures:

  { int n => 
    int m = n + 1; System.out.println(m * m); 
  }.invoke(3);  // will print 16
  

Implementation issue

This paragraph describes how the prototype compiler implements closures.

For each closure, the compiler will generate an interface with single method invoke(). E.g., for closure { => 42 }, the interface will look like:

  public interface I {
    int invoke();  // no arguments and return type int
  }
  

And for closure { int x, int y => x + y }, the interface will be like:

  public interface III {
    int invoke(int x, int y);  // two int arguments and return type int
  }
  

The interface will be in the javax.lang.function package. Then the compiler will generate an anonymous subclass of this interface, create an instance of this subclass, and call the invoke method. For example, the code

  public static void main(String[] args) {
    int answer = { => 42 }.invoke();
    System.out.println(answer);
  }
  

will be tranformed approximately as follows:

  public static void main(String[] args) {
    int answer = new javax.lang.function.I() {
      public int invoke() {
        return 42;
      }
    }.invoke();
    System.out.println(answer);
  }
  

So, at runtime a closure is represented as object. In JSR, this object is called the closure object.


Exercises

  1. Write a closure that returns the lesser of two double values.
  2. Write a closure that decides if a value is even.
  3. Write a closure that returns last n characters of a string.

Solutions

  double min1 = { double x, double y => x < y ? x : y }.invoke(7.5, 8.2);
  double min2 = { 
    double x, double y => 
    double m; if (x < y) m = x; else m = y; m 
  }.invoke(10.22, 9.76);
  
  boolean even = { int x => x % 2 == 0 }.invoke(15);
  
  { String, int => String } lastNChars = 
    { String s, int n => int len = s.length(); s.substring(len - n, len) };
  

33 comments:

jira said...

It is a little bit strange for me not using return keyword for returning a value from closure ... Don't you know why?

Zdeněk Troníček said...

The return keyword will return from the enclosing method. And yes, the syntax is weird and uncomfortable because you cannot return from closure earlier (before the end).

Mario Grgic said...

Is "fat arrow" notation a done deal now? What happened to the more "in Java spirit" original proposal syntax [ http://blogs.sun.com/roller/resources/ahe/closures.pdf ]?

martinval said...

As for
"The return keyword will return from the enclosing method":

This should be impossible if the closure is invoked after returning from that method. Perhaps an exception should result in such case - as has been suggested by John Rose.

Jens said...

Gosh, what an ugly syntax! :(

Anonymous said...

What's described here appear to be a cross between a lambda (anonymous functions) and a closures.

A lambda would return from itself, since it has it's own function scope.

For a lambda, think of a function (object/class method, whatever),

public int addFuction(int a, int b) { return a+b; }

then allow yourself to assign a variable to it

public int addVariable = addFunction;

then, remove all reference to the original name (ignore the syntax I'm using, it won't work... but it makes the idea visible).

public int addVariable = (int a, int b) { return a+b; };

A closure would return from the scope of it's current caller. They are very useful for designing new control structures. For example, if you only had the "while" control structure, you could define all the rest of the looping ones using it:

public void for(CodeBlock init, CodeBlock test, CodeBlock incr, CodeBlock body) {
init.apply();
while(test.apply()) {
body.apply();
incr.apply();
}
}

Don't look at the above for bugs and the like... it's just a general idea.

A continuation runs in the scope it was originally created in, so would return from there (and yes, it's possible).

Sorry for the ugly formatting, I couldn't figure out how to add preformatted text. It's also entirely possible I've horribly miscommunicated something.

Oto 'tapik' Buchta said...

I have to say that the closures in Java make me feel bad. Java was designed to be as simple and clear as possible. Functional programming in the Java model IMHO breaks the most beautiful feature of the Java language - readability.
I know it is a nice to have such feature in language, Python and LISP programming is easier thanks to such programming model, Lambda calculus is as strong as Turing machine. But I prefer clear and simple code.
So what's the main reason to add closures to Java?

Zdeněk Troníček said...

Hi tapik,

the code readability depends more on your knowledge and discipline than on language constructs that are available. In every language you can write cryptic code.

Regarding the motivation for closures, it is namely the boilerplate code. Definitely, it is not functional programming style.

old_bone said...

Do we really need the sequence ".invoke" ?

Zdeněk Troníček said...

Hi,

yes, I think we need it. Look here.

Anonymous said...

these closures for me looks like C code, full of *,-> and other idiotic mathematical signs with the only purpose of writing fever characters of code and newer opportunities of messing the code. It will make the code less readable and i can see by now idiots who don't now anything about OOP praising this syntax.

old_bone said...

So do we really need .invoke?
We have already some implicitly used things, like toString. It is defined as a method with a name, but in most cases you do not mention it when it in fact is called.

Though you may _optionally_ code it explicitly. Same logic could work for invoke.

old_bone said...

>> these closures for me looks like C code, full of *,-> and other idiotic mathematical signs with the only purpose of writing fever characters of code and newer opportunities of messing the code. It will make the code less readable and i can see by now idiots who don't now anything about OOP praising this syntax.

I agree with this. But it all happened not now and even not with Java. I recall reading (long ago) a FORTRAN textbook that recommended to use first identifiers A,B,C then AA, AB and so on. Reason? - it will save COMPILATION time. And that could be a true statement for the time.

And that stile made it into initial C. BUT there was a different experience even before C. Recall the ALGOL 68.

On closures. In ALGOL 68 (and not only in it) procedures body was considered as a value of another fundamental type. It could be assigned, passed as a parameter, returned by return and so on. I what was it worse than currently discussed closures?

Inventing the wheel.

It could be easily generalized for OOP. Classes would then contain only values, sub-classing would be equivalent to assigning a different default value to procedural variables (would be possible both for class and for instance - exactly anonymous _methods_ not classes! Currently we have to create anonymous classes when we in fact need to substitute a method.)

Delegation would look exactly as it does in C# - as an assignment of a procedural value.

All would look much much more consistent if this concept of procedural value was continued instead of being re-invented.

Alas: too late, too late.

Anonymous said...

Can someone point me to a step by step building the compiler using which i can actually feel through the closure syntax?

It would be great if i could test all this out ...

Regards
Vyas, Anirudh
Programming Thoughts @ Work!

Zdeněk Troníček said...

Hi,

download the prototype archive from http://www.javac.info, unpack it, and eventually change the batch files in the bin subdirectory. That's all.

Mathew said...

Although it means a language can really do alot of stuff but too much features in a language really makes it difficult to master.

ie. project A will be using closures,generics, etc.

project B using another set of features, slightly different paradigms..

worldhate said...

closure [kloh-zher]
–noun
1. a quick way to rape Java code.
2. complete mess that will eventually cost you your arm, your leg and your firstborn.
3. something too vile to define.

Anirudh Vyas said...

None of the examples, point me to idea of "free variables", all examples do some sort of processing on the arguments passed in, can someone post an example of external variables being referenced in a closure, cuz after all thats what this is all about ...

If its already there, Please accept my apologies, I'll look for it. Oh and thanks Zdenek, I was able to setup the prototype.

Regards
Vyas, Anirudh

Zdeněk Troníček said...

Hi Anirudh,

free variables are described in another post:
Local variables

Anirudh Vyas said...

Found one, For interested, the link is: Local Variable access

Anirudh Vyas said...

oh wow, even better, others, please ignore my link!

Thanks Zdenek! appreciate it.

Regards
Vyas, Anirudh

woody said...

Closures A closure is a form of anonymous function.Isn't what you're calling a closure actually a lambda function, or a function type ? I thought closure referred to the fact that function "encloses" and hence is bound to variables defined in the scope in which the function expression was was defined.

There is a lot of stuff on the web saying that anonyomous functions = closure. This isn't true. In other languages (like JavaScript for example) whether the function has a name or not has nothing to do with the fact that it continues to enjoy access to the variables in the scope it encloses. Thus I have a slight problem with the naming conventions used here.

Maybe it's me that's wrong with my definition ?

woody said...

To clarify, what I'm trying to say is that the Java definition of a "closure" used here appears slightly inconsitent with the use of the term "closure" in other languages. In other languages you can get closure without having to have anonymous functions. If we're saying that in Java a "closure" is a kind of anonymous function, then this seems to be different to other languages idea of closure, which is a language feature whereby function objects enjoy access to variables in the scope in which they were defined for as long as they (the function) live, and even if they live for longer than the function that provides the outer scope.

Zdeněk Troníček said...

Hi woody,

this blog is not a specification and it is written informally (sometimes less and sometimes more). This is one such place: although the closures specification distinguishes between closure literal and closure instance, I call them both simply a closure, because the difference is not important for a novice.

>There is a lot of stuff on the web saying
>that anonyomous functions = closure.
>This isn't true. In other languages
>(like JavaScript for example) whether
>the function has a name or not has
>nothing to do with the fact that it
>continues to enjoy access to the variables
>in the scope it encloses.

Right. Some languages have also named closures. My (informal) definition is valid only for the Java language.

Anonymous said...

Hello there,
Is closures.tar.gz applicable to Sun JDK only or is it compatible with the JDK v6 from other vendors as well ?
I am able to compile simple program with closures using the javac.bat provided. But with the java.bat it gives me as error
java.lang.ClassFormatError: JVMCFRE114 field name is invalid; class=SimpleClosure, offset=0
I did notuse Sun JDK

Can you please clarify

Zdeněk Troníček said...

As far as I know it works only with the Sun JDK. Use with other JDK was never tested (or I do not know of it).

Anonymous said...

Thanks.. I later verified that with -Xverify:no it works fine. So must be the class verifier is strict. Am aware of known differences in class verification between Sun and other implementations.

Anonymous said...

We should make Java Closure api more powerful.
Why we are just worry..that it look ugly.

Anonymous said...

This syntax is better IMO:

lambda(double x){Math.log(x)}

Oliver Maas said...

The first time i began to understand a closure was after reading a C# example, although i program only in Java and Delphi.

No .invoke(), no strange arrows necessary in C#.

The lambda expression looks like it's something new to Java, however i still don't get what's so special about the "enclosed" variable.

Somehow i have still the impression that we can get the same behaviour (with the same encapsulation) by using "traditional" means.

So far i haven't seen a closure example (in Java) which can't be reproduced by the means we have now. I still have the problem, that the Java examples which i have seen so far are giving me headaches.

Carlo said...

I agree with those that find the syntax weird.

{ int x => x + 1 }

Why not

(int x) { return x + 1; }

Ok, may it would be less easy for the compiler, but should be the compiler burden weigh on developers?

Carlo said...

I mean, there is already an idiom in Java for parameter specification and function body implementation.

Why introduce another idiom, totally unrelated?

Amit Phaltankar said...

Nice article!
As Java Closures - Lambda Expressions are set for release with Java SE 8, I have posted an introduction to Java 8 Closures with some examples.
Please visit the page and provide with your comments.
Detailed Introduction: Java Closures - Lambda Expressions with syntax details and examples programs