Java 7 : Oracle pushes a first version of closures

2 days ago, Oracle pushed a first version of the closures implementation. We can see the evolving syntax in the test cases they made for the Java compiler. You can see these test cases here.

This revision supports the following features (copied from revision) :

  • Function types syntax
  • Function types subtyping
  • Full support for lambda expression of type 1 and 2
  • Inference of thrown types/return type in a lambda
  • Lambda conversion using rules specified in v0.1.5 draft
  • Support references to ‘this’ (both explicit and implicit)
  • Translation using method handles

The function types aren’t enabled by default, so you have to use -XDallowFunctionTypes to enable it.

Here are some examples of lambda expression of type 1 taken from the test cases :

int i1 = #()(3).(); //i1 = 3
Integer i2 = #()(3).(); //i2 = 3
int i3 = #(int x)( x + 1 ).(3); //i3 = 4
int i4 = #(Number x)(x.intValue()).(new Float(3.0f)); //i4 = 3

And with type 2 :

int i1 = #(){ return 3; }.(); //i1 = 3
Integer i2 = #(){ return 3; }.(); //i2 = 3
int i3 = #(int x){ return x + 1; }.(3); //i3 = 4
int i4 = #(Number x){ return x.intValue(); }.(new Float(3.0f)); //i4 = 3

For those who didn’t understand the syntax, #(int x)( x + 1 ) declares a lambda expression that takes a int and return this int plus 1. And the . (dot) is used to invoke the lambda expression. So #(int x)( x + 1 ).(3) declares the lambda expression and invoke it with 3 as parameter.

This syntax is a little bit shocking, but I think we’ll get used.

 

  • http://Phi.Lho.free.fr PhiLho

    What is shocking (when first exposed to the syntax) is to see first the line int i1 = #()(3).(); as it seems totally cryptic on first sight.
    The line int i4 = #(Number x)(x.intValue()).(new Float(3.0f)); is somehow clearer, although I would have preferred to see first the assignment of the function (how it is declared?) then its usage.
    These lines might be great for testing syntax, but are a poor introduction to it! :-)

    Interesting sneak peek anyway, and well the syntax isn’t that ugly once I understand how the various parts articulate. :-D

    • Baptiste Wicht

      Effectively, the #()(3).() is completely unreadable.

      Normally, you could declare a function like that :

      #int() constant = #()(3);
      #int(int, int) adder = #(int x, int y)(x + y);

      But there is no examples in the test case of that. So I’m not sure of the choosen syntax.

      • Steve

        I have not seen the spec, but we should hope that the declaration syntax is not as you suggest, e.g.

        #int(int, int) adder = #(int x, int y)(x + y);

        This would be similar to the original verbose generics syntax with duplicate type declarations. It seems this would be sufficient:

        #int adder = #(int x, int y)(x + y);

        • Baptiste Wicht

          I think it’s not sufficient. We must specify the arguments in the declaration. Without that, how could we pass it to other method or safely invoke it after declaration ?

          • Steve

            The compiler will see the arguments and their type specified on the right hand side so there is no need to specify the type again on the left. Guillaume’s suggestion below is in the same vein.

            I just noticed this too, the dot notation for invocation sort of makes the closures second class functions with respect to call. I would think something like this would make more sense:

            #int adder = #(int x, int y){ x + y };
            sum = adder(1,2);

            Line 1 declares a variable of type #int, a lambda returning an int, and its definition is on the RHS. This convention is more consistent with Java declarations for simple types than #int(int x, int y) which looks similar to the Java generics schema.

            Line 2 calls adder like any other function.

            For debugging, an optional name can be permitted after the # on the RHS.

      • http://gaelyk.appspot.com Guillaume Laforge

        Instead of:
        #int(int, int) adder = #(int x, int y)(x + y);
        That would be nicer to have something like this for example:
        #int(int x, int y) adder = x + y;
        There’s certainly room for improvement.
        I’d also find it nicer to read if we could do adder(1, 2) instead of adder.(1, 2) with that dot in-between, which doesn’t sound very Java-ish.

        • Baptiste Wicht

          For your proposal

          #int(int x, int y) adder = x + y;

          I think it’s to easy, how could the compiler do that = x + y is still a valid operation to do. And more, i find it’s not really clear to read, we can think we put the result of the addition of x and y to the adder variable. A better would be :

          #int(int x, int y) adder = #{x + y};

          But not very clear too I think.

          I agree with adder(1, 2) as invocation but that will add some new problems. What to choose between a closure and a method with the same name, it could be tricky to debug such stuff.

          I think added.(1,2), is not bad. I consider it as invoking an anonymous method on an object.

  • http://Phi.Lho.free.fr PhiLho

    What is shocking (when first exposed to the syntax) is to see first the line int i1 = #()(3).(); as it seems totally cryptic on first sight.
    The line int i4 = #(Number x)(x.intValue()).(new Float(3.0f)); is somehow clearer, although I would have preferred to see first the assignment of the function (how it is declared?) then its usage.
    These lines might be great for testing syntax, but are a poor introduction to it! :-)

    Interesting sneak peek anyway, and well the syntax isn’t that ugly once I understand how the various parts articulate. :-D

    • Baptiste Wicht

      Effectively, the #()(3).() is completely unreadable.

      Normally, you could declare a function like that :

      #int() constant = #()(3);
      #int(int, int) adder = #(int x, int y)(x + y);

      But there is no examples in the test case of that. So I’m not sure of the choosen syntax.

      • Steve

        I have not seen the spec, but we should hope that the declaration syntax is not as you suggest, e.g.

        #int(int, int) adder = #(int x, int y)(x + y);

        This would be similar to the original verbose generics syntax with duplicate type declarations. It seems this would be sufficient:

        #int adder = #(int x, int y)(x + y);

        • Baptiste Wicht

          I think it’s not sufficient. We must specify the arguments in the declaration. Without that, how could we pass it to other method or safely invoke it after declaration ?

          • Steve

            The compiler will see the arguments and their type specified on the right hand side so there is no need to specify the type again on the left. Guillaume’s suggestion below is in the same vein.

            I just noticed this too, the dot notation for invocation sort of makes the closures second class functions with respect to call. I would think something like this would make more sense:

            #int adder = #(int x, int y){ x + y };
            sum = adder(1,2);

            Line 1 declares a variable of type #int, a lambda returning an int, and its definition is on the RHS. This convention is more consistent with Java declarations for simple types than #int(int x, int y) which looks similar to the Java generics schema.

            Line 2 calls adder like any other function.

            For debugging, an optional name can be permitted after the # on the RHS.

      • http://gaelyk.appspot.com Guillaume Laforge

        Instead of:
        #int(int, int) adder = #(int x, int y)(x + y);
        That would be nicer to have something like this for example:
        #int(int x, int y) adder = x + y;
        There’s certainly room for improvement.
        I’d also find it nicer to read if we could do adder(1, 2) instead of adder.(1, 2) with that dot in-between, which doesn’t sound very Java-ish.

        • Baptiste Wicht

          For your proposal

          #int(int x, int y) adder = x + y;

          I think it’s to easy, how could the compiler do that = x + y is still a valid operation to do. And more, i find it’s not really clear to read, we can think we put the result of the addition of x and y to the adder variable. A better would be :

          #int(int x, int y) adder = #{x + y};

          But not very clear too I think.

          I agree with adder(1, 2) as invocation but that will add some new problems. What to choose between a closure and a method with the same name, it could be tricky to debug such stuff.

          I think added.(1,2), is not bad. I consider it as invoking an anonymous method on an object.

  • Brakebein

    Really ugly imho. But then again, I was never a fan of including them in Java.

  • Brakebein

    Really ugly imho. But then again, I was never a fan of including them in Java.

  • zilti

    As far as I’ve understood them (I haven’t used them in Java yet)
    int i1 = #()(3).();
    is just a short way of writing this:
    int il = #()(3); // Declare
    il.(); // Invoke
    So after all I don’t think it’s less readable than anything else in Java that uses a short writing.

    • Baptiste Wicht

      No

      int i1 = #()(3).();

      declares and invoke the methods with no parameters. But

      int il = #()(3); // Declare

      Is not correct because it’s not a int, it’s a closure (lambda expression). The equivalent is

      #int() il = #()(3); // Declare
      int i1 = il.(); //Invoke

  • zilti

    As far as I’ve understood them (I haven’t used them in Java yet)
    int i1 = #()(3).();
    is just a short way of writing this:
    int il = #()(3); // Declare
    il.(); // Invoke
    So after all I don’t think it’s less readable than anything else in Java that uses a short writing.

    • Baptiste Wicht

      No

      int i1 = #()(3).();

      declares and invoke the methods with no parameters. But

      int il = #()(3); // Declare

      Is not correct because it’s not a int, it’s a closure (lambda expression). The equivalent is

      #int() il = #()(3); // Declare
      int i1 = il.(); //Invoke

  • John

    Why not just promote scala to be the primary language on the jvm. With this terrible syntax I can see becoming even more popular

    • Rahul G

      Couldn’t agree more! :-)

      • Me

        1. Scala has compatibility problems. Every upgrade requires recompilation. Let me clarify: recompilation of your application code and every third-party library code (that is written in Scala). You can just drop Spring-0.9.jar or log4j-0.3-alpha.jar in your application, compiled with IBM JDK 1.1, and they will work on the latest JRE. Backwards *binary* compatilibity is one key of the success of Java, don’t mess with that.

        2. Do you use Scala in production today? Do you know anyone who does? Don’t try to sell something you don’t use yourself.

        • http://code.google.com/p/lambdaj/ Mario Fusco

          > Do you use Scala in production today?
          Yes, I do.

          > Do you know anyone who does?
          Yes, I do: http://www.scala-lang.org/node/1658

        • http://logji.blogspot.com nuttycom

          I’ve used Scala in production since 2.7.1 at two different companies. Binary compatibility is an issue, but dealing with binary compatibility issues is foremost among the problems that Martin and crew have lined up to address in the near future.

          Nobody knows whether it will ever achieve the market penetration of Java, but I feel pretty safe in saying that companies that decide to adopt Scala into their environments will have a nontrivial competitive advantage over those who decide to stick with java, even given the rough spots that come with using a developing language. The productivity and safety gains available are pretty astonishing once you get over the learning hump.

    • Oscar

      Just for the sake of the comparison, I “think” this would be the equivalent Scala:

      val i1 = (() => 3)() //i1: Int = 3
      val i2 :Number = (() => 3)() //i2: java.lang.Number = 3
      val i3 = ((x:Int) => x+1)(3) //i3: Int = 4
      val i4 = ( (x:Number) => x.intValue())(3.0f) //i4: Int = 3

  • John

    Why not just promote scala to be the primary language on the jvm. With this terrible syntax I can see becoming even more popular

    • Rahul G

      Couldn’t agree more! :-)

      • Me

        1. Scala has compatibility problems. Every upgrade requires recompilation. Let me clarify: recompilation of your application code and every third-party library code (that is written in Scala). You can just drop Spring-0.9.jar or log4j-0.3-alpha.jar in your application, compiled with IBM JDK 1.1, and they will work on the latest JRE. Backwards *binary* compatilibity is one key of the success of Java, don’t mess with that.

        2. Do you use Scala in production today? Do you know anyone who does? Don’t try to sell something you don’t use yourself.

        • http://code.google.com/p/lambdaj/ Mario Fusco

          > Do you use Scala in production today?
          Yes, I do.

          > Do you know anyone who does?
          Yes, I do: http://www.scala-lang.org/node/1658

        • http://logji.blogspot.com nuttycom

          I’ve used Scala in production since 2.7.1 at two different companies. Binary compatibility is an issue, but dealing with binary compatibility issues is foremost among the problems that Martin and crew have lined up to address in the near future.

          Nobody knows whether it will ever achieve the market penetration of Java, but I feel pretty safe in saying that companies that decide to adopt Scala into their environments will have a nontrivial competitive advantage over those who decide to stick with java, even given the rough spots that come with using a developing language. The productivity and safety gains available are pretty astonishing once you get over the learning hump.

    • Oscar

      Just for the sake of the comparison, I “think” this would be the equivalent Scala:

      val i1 = (() => 3)() //i1: Int = 3
      val i2 :Number = (() => 3)() //i2: java.lang.Number = 3
      val i3 = ((x:Int) => x+1)(3) //i3: Int = 4
      val i4 = ( (x:Number) => x.intValue())(3.0f) //i4: Int = 3

  • Sven D

    Hm the syntax couldn’t be uglier. They should just adopt the closure syntax of Groovy:

    Closure c = {int x -> return x+1} // or simply {x -> x+1}
    int y = c(5) // or c.call(5)
    assert y == 6

    So consise and readable…

    • Baptiste Wicht

      But with Closure as type, we don’t know the return type and the arguments and so there is no compile time check.

      I don’t find the Groovy syntax clearer than this of Java 7. But this is only my opinion.

      • http://pacman.blog.br Tiago Peczenyj

        But this way…

        Closure half = {int x -> return x/2.0}
        Float y = half(1024) // or half.call(1024)
        assertEquals(512.0,y);

        Is more readable than

        #(int x)( x /2.0 ).(1024);

        And we can check in compile time.

        My 2 cents

        • http://pacman.blog.br Tiago Peczenyj

          ops…

          Closure<Float> half = {int x -> return x/2.0}

          • Baptiste Wicht

            Yes, but we can only check the return types, what about the parameters ?

            I think the choosen syntax it’s not as bad as we can think if we know that we must include the return type and the parameters types.

        • Michael

          As auto conversion to SAM seems to be in:

          Closure half = #(int x) { return x/2.0 }; // or #(int x) (x/2.0)
          Float y = half.(1024) /* why the dot needs to be there is mentioned elsewhere on this page */
          assertEquals(512.0,y);

          the only significant difference seems to be ‘->’ which, if it really hurts your eyes, you could write an ide plugin for that drew and actual arrow instead of two chars pretending to be one.

    • Michael

      now write a multi-line closure.

      That said using () and to some extends [] is horrible whats wrong with {} again?

      • Baptiste Wicht

        {} are used to write multiline closures :

        #int(int, int) il = #(int x, int y){
        int z = x * 2 + y * 6;
        //more operations
        return z * z;
        };

        • Michael

          The multi-line comment was aimed at ‘syntax of Groovy’
          http://groovy.codehaus.org/Closures+-+Informal+Guide

          I don’t know I still think the groovy syntax seems to fall apart, though I must say that I agree with the above statements that you can get used to about anything.

          either way I favor the currently proposed way over the groovy way. One thing I must say is that it seems hard to differentiate between {( and [ in given de blog’s font – though that could be because I’m missing fonts(using ubuntu).

          Any way I see now that this boils down to the type 1 and type 2 you are referring about one uses round braces and implicitly returns other uses curly braces and requires an explicit return. – Why are those round braces necessary? (are they even – the last version on javac.info doesn’t seem to feature them)

  • Sven D

    Hm the syntax couldn’t be uglier. They should just adopt the closure syntax of Groovy:

    Closure c = {int x -> return x+1} // or simply {x -> x+1}
    int y = c(5) // or c.call(5)
    assert y == 6

    So consise and readable…

    • Baptiste Wicht

      But with Closure as type, we don’t know the return type and the arguments and so there is no compile time check.

      I don’t find the Groovy syntax clearer than this of Java 7. But this is only my opinion.

      • http://pacman.blog.br Tiago Peczenyj

        But this way…

        Closure half = {int x -> return x/2.0}
        Float y = half(1024) // or half.call(1024)
        assertEquals(512.0,y);

        Is more readable than

        #(int x)( x /2.0 ).(1024);

        And we can check in compile time.

        My 2 cents

        • http://pacman.blog.br Tiago Peczenyj

          ops…

          Closure<Float> half = {int x -> return x/2.0}

          • Baptiste Wicht

            Yes, but we can only check the return types, what about the parameters ?

            I think the choosen syntax it’s not as bad as we can think if we know that we must include the return type and the parameters types.

        • Michael

          As auto conversion to SAM seems to be in:

          Closure half = #(int x) { return x/2.0 }; // or #(int x) (x/2.0)
          Float y = half.(1024) /* why the dot needs to be there is mentioned elsewhere on this page */
          assertEquals(512.0,y);

          the only significant difference seems to be ‘->’ which, if it really hurts your eyes, you could write an ide plugin for that drew and actual arrow instead of two chars pretending to be one.

    • Michael

      now write a multi-line closure.

      That said using () and to some extends [] is horrible whats wrong with {} again?

      • Baptiste Wicht

        {} are used to write multiline closures :

        #int(int, int) il = #(int x, int y){
        int z = x * 2 + y * 6;
        //more operations
        return z * z;
        };

        • Michael

          The multi-line comment was aimed at ‘syntax of Groovy’
          http://groovy.codehaus.org/Closures+-+Informal+Guide

          I don’t know I still think the groovy syntax seems to fall apart, though I must say that I agree with the above statements that you can get used to about anything.

          either way I favor the currently proposed way over the groovy way. One thing I must say is that it seems hard to differentiate between {( and [ in given de blog’s font – though that could be because I’m missing fonts(using ubuntu).

          Any way I see now that this boils down to the type 1 and type 2 you are referring about one uses round braces and implicitly returns other uses curly braces and requires an explicit return. – Why are those round braces necessary? (are they even – the last version on javac.info doesn’t seem to feature them)

  • http://blog.visitanywhere.info Dennis

    The syntax may be ugly, but at least it is explicit – that is # to indicate a closure, the arguments, then the body. I use the C# syntax quite a bit (it is much the same as the groovy syntax) and while I am used to it there is nothing that in C# that prepares developers to understand it, and so newcomers find it confusing also.

    The important thing is to move forward on the finalization and implementation, we will get used to the syntax whatever it is. Its time to decide and not to debate.

  • http://blog.visitanywhere.info Dennis

    The syntax may be ugly, but at least it is explicit – that is # to indicate a closure, the arguments, then the body. I use the C# syntax quite a bit (it is much the same as the groovy syntax) and while I am used to it there is nothing that in C# that prepares developers to understand it, and so newcomers find it confusing also.

    The important thing is to move forward on the finalization and implementation, we will get used to the syntax whatever it is. Its time to decide and not to debate.

  • qinxian

    Tool is Contexted.
    Can you tell the world, Who use the the uglies:
    int i1 = #()(3).(); //i1 = 3
    Integer i2 = #()(3).(); //i2 = 3
    int i3 = #(int x)( x + 1 ).(3); //i3 = 4
    int i4 = #(Number x)(x.intValue()).(new Float(3.0f)); //i4 = 3
    You, and me, Human being, not Machine being. huh?

  • qinxian

    Tool is Contexted.
    Can you tell the world, Who use the the uglies:
    int i1 = #()(3).(); //i1 = 3
    Integer i2 = #()(3).(); //i2 = 3
    int i3 = #(int x)( x + 1 ).(3); //i3 = 4
    int i4 = #(Number x)(x.intValue()).(new Float(3.0f)); //i4 = 3
    You, and me, Human being, not Machine being. huh?

  • Henk

    Qinxian, those are just abbreviated unit test examples. In real code you don’t define a lambda and immediately call it just to get a constant.

    Instead, you’ll pass the lambda reference to something and that something will store and call it. The syntax will look pretty decent then.

    Please think before you rant.

    • qinxian

      Henk, thank you explained, through I subscribed in lambda mail list.:)
      1, I just point out it, not rant. No worth to rant for the Old Stone. BTW, you know, some one still using the stone.
      2, Context is important. This style of syntax just add burden for people.
      3, The blog differ from the lambda mail list, isn’t it?
      4, Why lambda exist long but not hot?
      5, As to the unit test example, it no value to exist, although it just an unit test example, as you speaking, people should not use it by this way.

      So Please think before you think it as rant.

  • Henk

    Qinxian, those are just abbreviated unit test examples. In real code you don’t define a lambda and immediately call it just to get a constant.

    Instead, you’ll pass the lambda reference to something and that something will store and call it. The syntax will look pretty decent then.

    Please think before you rant.

    • qinxian

      Henk, thank you explained, through I subscribed in lambda mail list.:)
      1, I just point out it, not rant. No worth to rant for the Old Stone. BTW, you know, some one still using the stone.
      2, Context is important. This style of syntax just add burden for people.
      3, The blog differ from the lambda mail list, isn’t it?
      4, Why lambda exist long but not hot?
      5, As to the unit test example, it no value to exist, although it just an unit test example, as you speaking, people should not use it by this way.

      So Please think before you think it as rant.

  • Santosh Gokak

    How would exception handling and thread safety work n case of closures? links will help :)

    • Baptiste Wicht

      They added more files. We can say that a lambda expression throws an exception :

      #void(int,int,int)(throws Exception) lambda = #(int i1, int i2, int i3) { /* Some code */ };

      But they also added a way to cast lambda to interface type :

      public class LambdaConv02 {
          interface A { void f(int i1, int i2, int i3) throws Exception; }
          interface B { void f(int i1, int i2, int i3); }
          interface C extends A, B {}
      
          static int assertionCount = 0;
      
          public static void main(String[] args) throws Exception {
              #void(int,int,int)(throws Exception) lambda = #(int i1, int i2, int i3) {/* Some code */};
              lambda.(1,2,3);
              C foo1 = lambda;
              foo1.f(3,4,7);
          }
      }

      But I think it’s not really clear. How can we assign a lambda expression to a type who has a fonction with the same signature as the lamda ? For me it sounds weird :(

      • http://jawher.wordpress.com/ Jawher

        The fact that lambdas are compatible with SAM types (types with a single abstract method) doesn’t look weird to me: Most SAMs exist because the only way to pass code around in Java is to use class instances (think Comparator, Runnable, Callable, etc.).

        With lambdas, that limitation no longer exist, but the totality of Java APIs out there (the jvm ones like collections and the others) were written in the before-lambdas era and so they rely on SAMs.

        It would be a shame if old APIs would not benefit from lambdas. They just can’t be changed to accept lambdas (like adding a filter method to java.util.List that taks a predicate lambda) because that would break backward compatibility.

        The automatic conversion between lambdas and SAMs is the perfect solution to this.

        • Baptiste Wicht

          Thanks for that explanation Jawher :)

          It’s a lot clearer. I didn’t think of the compatibility with the current API.

          • Michael

            If you want to use method-chaining, overloading et al you still need something stronger typed then some generic closure. With closures you even it it’s current proposed form you throw some Strong Typing out the window.

            How is anyone going to differenciate between:

            #boolean(Item) and #boolean(Item)

            buildFilters()
            .add((InclusionRule) #boolean(Item item) {item.isFast()} )
            .add((ExclusionRule) #boolean(Item item) {item.isDefective()})

            Offcourse this is a really poor example and you probably want to not have to cast it. And yes in this case you can simply flip the logic. And yes you can use the method name to differentiate…

  • Santosh Gokak

    How would exception handling and thread safety work n case of closures? links will help :)

    • Baptiste Wicht

      They added more files. We can say that a lambda expression throws an exception :

      #void(int,int,int)(throws Exception) lambda = #(int i1, int i2, int i3) { /* Some code */ };

      But they also added a way to cast lambda to interface type :

      public class LambdaConv02 {
          interface A { void f(int i1, int i2, int i3) throws Exception; }
          interface B { void f(int i1, int i2, int i3); }
          interface C extends A, B {}
      
          static int assertionCount = 0;
      
          public static void main(String[] args) throws Exception {
              #void(int,int,int)(throws Exception) lambda = #(int i1, int i2, int i3) {/* Some code */};
              lambda.(1,2,3);
              C foo1 = lambda;
              foo1.f(3,4,7);
          }
      }

      But I think it’s not really clear. How can we assign a lambda expression to a type who has a fonction with the same signature as the lamda ? For me it sounds weird :(

      • http://jawher.wordpress.com/ Jawher

        The fact that lambdas are compatible with SAM types (types with a single abstract method) doesn’t look weird to me: Most SAMs exist because the only way to pass code around in Java is to use class instances (think Comparator, Runnable, Callable, etc.).

        With lambdas, that limitation no longer exist, but the totality of Java APIs out there (the jvm ones like collections and the others) were written in the before-lambdas era and so they rely on SAMs.

        It would be a shame if old APIs would not benefit from lambdas. They just can’t be changed to accept lambdas (like adding a filter method to java.util.List that taks a predicate lambda) because that would break backward compatibility.

        The automatic conversion between lambdas and SAMs is the perfect solution to this.

        • Baptiste Wicht

          Thanks for that explanation Jawher :)

          It’s a lot clearer. I didn’t think of the compatibility with the current API.

          • Michael

            If you want to use method-chaining, overloading et al you still need something stronger typed then some generic closure. With closures you even it it’s current proposed form you throw some Strong Typing out the window.

            How is anyone going to differenciate between:

            #boolean(Item) and #boolean(Item)

            buildFilters()
            .add((InclusionRule) #boolean(Item item) {item.isFast()} )
            .add((ExclusionRule) #boolean(Item item) {item.isDefective()})

            Offcourse this is a really poor example and you probably want to not have to cast it. And yes in this case you can simply flip the logic. And yes you can use the method name to differentiate…

  • Howard Lovatt

    They have proposed lambda types and Single Abstract method (SAM) conversions. The proposed syntax for a lambda type is:

    #int(int) inc = #(int x)(x+1);
    // or #(int x){return x+1} or #int(int x){return x+1} or #int(int x)(x+1)

    The proposed syntax for a SAM conversion is:

    FileFilter dirFilter = #(File f)(f.isDirectory());

    The SAM conversions may be for interfaces, not abstract classes. The problem with a class is that a constructor might throw an exception and Java has checked exceptions.

    The syntax for calling a lambda requires the dot before the brackets to distinguish a call to a lambda field from a call to a method of the same name (fields and methods can have the same name in Java).

    See http://mail.openjdk.java.net/mailman/listinfo/lambda-dev for the ongoing discussions.

  • Howard Lovatt

    They have proposed lambda types and Single Abstract method (SAM) conversions. The proposed syntax for a lambda type is:

    #int(int) inc = #(int x)(x+1);
    // or #(int x){return x+1} or #int(int x){return x+1} or #int(int x)(x+1)

    The proposed syntax for a SAM conversion is:

    FileFilter dirFilter = #(File f)(f.isDirectory());

    The SAM conversions may be for interfaces, not abstract classes. The problem with a class is that a constructor might throw an exception and Java has checked exceptions.

    The syntax for calling a lambda requires the dot before the brackets to distinguish a call to a lambda field from a call to a method of the same name (fields and methods can have the same name in Java).

    See http://mail.openjdk.java.net/mailman/listinfo/lambda-dev for the ongoing discussions.

  • http://www.mrico.eu Marco Rico

    I definitely prefer the Scala way:

    val i1 = ( () => 3 )()
    val i2 = ( () => 3 )()
    val i3 = ( (x: Int) => x + 1 )(3)
    val i4 = ( (x: Number) => x.intValue )(3.0f)

    It is much more readable than the equivalent Java code!

    • http://jawher.wordpress.com/ Jawher

      According to Maurizio Cimadamore (who seems to be in charge of implementing lambdas in the javac compiler), the main reason behind choosing the strawman syntax for lambdas is that it’s an LL(1) grammar and easy to parse, thus allowing them to concentrate on the semantics rather on the syntax.

  • http://www.mrico.eu Marco Rico

    I definitely prefer the Scala way:

    val i1 = ( () => 3 )()
    val i2 = ( () => 3 )()
    val i3 = ( (x: Int) => x + 1 )(3)
    val i4 = ( (x: Number) => x.intValue )(3.0f)

    It is much more readable than the equivalent Java code!

    • http://jawher.wordpress.com/ Jawher

      According to Maurizio Cimadamore (who seems to be in charge of implementing lambdas in the javac compiler), the main reason behind choosing the strawman syntax for lambdas is that it’s an LL(1) grammar and easy to parse, thus allowing them to concentrate on the semantics rather on the syntax.

  • http://ceilingfish.net Tom

    Is it me or would a compromise between the two syntaxes seem more intuitive:

    int i1 = #(){ 3; }.(); //i1 = 3
    Integer i2 = #(){ 3; }.(); //i2 = 3
    int i3 = #(int x){ x + 1; }.(3); //i3 = 4
    int i4 = #(Number x){ x.intValue(); }.(new Float(3.0f)); //i4 = 3

    Basically, the second format, but without the extra boilerplate of “return “. I’ve probably been writing too much Ruby though!

  • http://ceilingfish.net Tom

    Is it me or would a compromise between the two syntaxes seem more intuitive:

    int i1 = #(){ 3; }.(); //i1 = 3
    Integer i2 = #(){ 3; }.(); //i2 = 3
    int i3 = #(int x){ x + 1; }.(3); //i3 = 4
    int i4 = #(Number x){ x.intValue(); }.(new Float(3.0f)); //i4 = 3

    Basically, the second format, but without the extra boilerplate of “return “. I’ve probably been writing too much Ruby though!

  • Ivan

    Looks more like anonymous functions to me… Why are all the examples invoking immediately?

    Where’s the part where I can take the closure, and pass it around? are they going to create a new keyword?

    closure f1 = #(){ 3; };

    ?

    • http://jawher.wordpress.com/ Jawher

      There are lambda types so that you can declare a lambda typed variable, field or argument:

      public class SortedList {
      	private #int(String, String) comparator;
      
      public SortedList(#int(String, String) comparator){
      	this.comparator=comparator;
      }
      
      public void sort(){
      	Collections.sort(list, comparator);
      }
      :
      :
      }
      

      And then, you can pass a lambda expression this way:

      SortedList l = new SortedList(#int(String s1, String s2)(s1.compareTo(s2));
      
  • Ivan

    Looks more like anonymous functions to me… Why are all the examples invoking immediately?

    Where’s the part where I can take the closure, and pass it around? are they going to create a new keyword?

    closure f1 = #(){ 3; };

    ?

    • http://jawher.wordpress.com/ Jawher

      There are lambda types so that you can declare a lambda typed variable, field or argument:

      public class SortedList {
      	private #int(String, String) comparator;
      
      public SortedList(#int(String, String) comparator){
      	this.comparator=comparator;
      }
      
      public void sort(){
      	Collections.sort(list, comparator);
      }
      :
      :
      }
      

      And then, you can pass a lambda expression this way:

      SortedList l = new SortedList(#int(String s1, String s2)(s1.compareTo(s2));
      
  • Ivan

    Thinking a little more, I guess maybe closure would probably be implemented as a type with varargs of objects?

  • Ivan

    Thinking a little more, I guess maybe closure would probably be implemented as a type with varargs of objects?

  • Brian Goetz

    Bear in mind this is an early, proof-of-concept snapshot drop. The syntax shown here is entirely provisional and will get a thorough workover as Project Lambda progresses. In the meantime there are far more important issues than syntax, and these will be getting our full attention until they are worked out — syntax can wait.

    • Baptiste Wicht

      Thanks for coming and make that clearer to us. And thanks too for the work on closures.

  • Brian Goetz

    Bear in mind this is an early, proof-of-concept snapshot drop. The syntax shown here is entirely provisional and will get a thorough workover as Project Lambda progresses. In the meantime there are far more important issues than syntax, and these will be getting our full attention until they are worked out — syntax can wait.

    • Baptiste Wicht

      Thanks for coming and make that clearer to us. And thanks too for the work on closures.

  • Ivan

    Interesting concept! The syntax looks great for a first draft to me. I suspect most people don’t use closures. I’m not sure there’s any language where they look amazing syntactically – especially after you start capturing context and invoking later…

    I’m very excited about it :)

  • Ivan

    Interesting concept! The syntax looks great for a first draft to me. I suspect most people don’t use closures. I’m not sure there’s any language where they look amazing syntactically – especially after you start capturing context and invoking later…

    I’m very excited about it :)

  • Jon

    This would be great for handling interfaces that could return null.

    checkNullPointer(#Object2(){ return Object1.getNullable().getNullabler().getNullablerest(); });

    protected static T checkNullPointer(#T() lambda)
    {
    try
    {
    return lambda.()
    } catch( NullPointerException npex )
    {
    return null;
    }
    }

    I think there is opportunity to clean up the syntax especially when there are no parameters or a void return type.

    #int(){ return something(); } –> #int{ return something(); }
    #void()( doSomething() ) –> #{ doSomething(); }
    lambda.() –> lambda.

    Thirdly, I wonder if the Oracle devs would allow the use of the generics wildcard in which case the compiler would infer the return type of the lambda. It is a shot in the dark and doesn’t fit well with normal Java conventions (you can’t do similarly with method returns); however, it has more utility with lambdas. My checkNullPointer lambda example would be less prone to developer errors if the compiler inferred them.

    #(Object x){ return someObjectofTypeSubObject(x) }

    • Jon

      the comment box ate my generics. The involved lines:

      protected static T <T> checkNullPointer(#T() lambda)

      #<>(Object x){ return someObjectofTypeSubObject(x) }

  • Jon

    This would be great for handling interfaces that could return null.

    checkNullPointer(#Object2(){ return Object1.getNullable().getNullabler().getNullablerest(); });

    protected static T checkNullPointer(#T() lambda)
    {
    try
    {
    return lambda.()
    } catch( NullPointerException npex )
    {
    return null;
    }
    }

    I think there is opportunity to clean up the syntax especially when there are no parameters or a void return type.

    #int(){ return something(); } –> #int{ return something(); }
    #void()( doSomething() ) –> #{ doSomething(); }
    lambda.() –> lambda.

    Thirdly, I wonder if the Oracle devs would allow the use of the generics wildcard in which case the compiler would infer the return type of the lambda. It is a shot in the dark and doesn’t fit well with normal Java conventions (you can’t do similarly with method returns); however, it has more utility with lambdas. My checkNullPointer lambda example would be less prone to developer errors if the compiler inferred them.

    #(Object x){ return someObjectofTypeSubObject(x) }

    • Jon

      the comment box ate my generics. The involved lines:

      protected static T <T> checkNullPointer(#T() lambda)

      #<>(Object x){ return someObjectofTypeSubObject(x) }

  • Hugh

    Drop the ‘#’ use ‘$’ instead, maybe. Is $()(3).() better than #()(3).(). Like Scala better

    • http://Phi.Lho.free.fr PhiLho

      It can’t work in Java, you can already declare a function named $
      Bad idea, indeed, but doable.
      Beside, I don’t see an advantage of using one symbol instead of the other…

      • Hugh

        Doh! Didn’t know one could start a variable with ‘$’in Java. Have seen and used (habit from from C days) variables starting with ‘_’, never ‘$’. Still, the Java “closure” syntax is ugly and the ‘#’ makes it uglier. It’s all a matter of aesthetics. The ‘$’ is more “svelte” and comes closer to a Greek lambda. The ‘#’ looks like a smashed bug on a car’s windshield.

        • http://Phi.Lho.free.fr PhiLho

          For the record, using $ is legal in Java, but strongly discouraged: it is reserved by the compiler to make internal identifiers. You can see some of them in the generated class files (names of “anonymous” classes).
          I like the “smashed bug on a car’s windshield” analogy… :-) C# developers might appreciate (they probably smash bugs daily!).

  • Hugh

    Drop the ‘#’ use ‘$’ instead, maybe. Is $()(3).() better than #()(3).(). Like Scala better

    • http://Phi.Lho.free.fr PhiLho

      It can’t work in Java, you can already declare a function named $
      Bad idea, indeed, but doable.
      Beside, I don’t see an advantage of using one symbol instead of the other…

      • Hugh

        Doh! Didn’t know one could start a variable with ‘$’in Java. Have seen and used (habit from from C days) variables starting with ‘_’, never ‘$’. Still, the Java “closure” syntax is ugly and the ‘#’ makes it uglier. It’s all a matter of aesthetics. The ‘$’ is more “svelte” and comes closer to a Greek lambda. The ‘#’ looks like a smashed bug on a car’s windshield.

        • http://Phi.Lho.free.fr PhiLho

          For the record, using $ is legal in Java, but strongly discouraged: it is reserved by the compiler to make internal identifiers. You can see some of them in the generated class files (names of “anonymous” classes).
          I like the “smashed bug on a car’s windshield” analogy… :-) C# developers might appreciate (they probably smash bugs daily!).

  • http://freemusicformormons.com/lds-ward-choir-music roger pack

    oh man that is ugly.  But maybe we’ll get used to it.

    • Anonymous

      Maybe :)

      Personnally, I prefer C++ or C# syntax, but that’s only a matter of style, the important part is the feature provided by the closure itself.