Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

closures in groovy vs closures in java 8 (lambda expressions)?

Given doSomething(Function foo) { println foo(2) }

Groovy: doSomething( { it*it } as Function )

Java: doSomething( (x) -> x*x )

Is there any difference between the two?

like image 201
Harpreet Singh Avatar asked Sep 17 '13 05:09

Harpreet Singh


People also ask

What is the difference between closure and lambda?

Lambda functions may be implemented as closures, but they are not closures themselves. This really depends on the context in which you use your application and the environment. When you are creating a lambda function that uses non-local variables, it must be implemented as a closure.

What are closures in Groovy?

A closure in Groovy is an open, anonymous, block of code that can take arguments, return a value and be assigned to a variable. A closure may reference variables declared in its surrounding scope.

What is closure lambda?

A lambda closure is created when a lambda expression references the variables of an enclosing scope (global or local). The rules for doing this are the same as those for inline methods and anonymous classes. Local variables from an enclosing scope that are used within a lambda have to be final .

What is closures in Java?

Closures are the inline-function valued expressions which means that they are the class functions with bounded variables. Closures can be passed to another function as a parameter. A closure gives us access to the outer function from an inner function.


2 Answers

In Groovy, closures are first class citizens of type groovy.lang.Closure, whereas lambdas in Java 8 are actual instances of the default method interface they represent.

This means you need to use the as keyword in Groovy (as you've shown), but alternatively, in Java you need to specify an interface, so in Groovy, you could do:

def adder( int i, Closure cl ) {
    cl( i )
}

int v = adder( 2 ) { i ->
    i + 8
}

assert v == 10

This in Java 8 becomes:

public class Test {
    interface MyAdder {
        int call( int i ) ;
    }

    public int adder( int i, MyAdder adder ) {
        return adder.call( i ) ;
    }

    public static void main( String[] args ) {
        int v = new Test().adder( 2, (x) -> x + 8 ) ;
        System.out.println( v ) ;
    }
}

Obviously, you can also now declare default implementation in interfaces, which I didn't show here...

Not sure if this is all the differences, but it's a difference at least ;-)

like image 155
tim_yates Avatar answered Sep 22 '22 03:09

tim_yates


  • In Java Lambda Expressions there is no way to refer to the parameters of the lambda expressions by default name. There is something on similar lines in Groovy I think it is "it".
  • In Java Lambda expressions represent a convenient way to implement Single Abstract Method classes/interfaces. So if you have to create a lambda expression for something, you got to have a SAM interface defined for it.
  • In Java, Lambda expressions can capture only those variable which are effectively final.
  • In Java, there is an alternate way to represent a Lambda expression by using something called Method References. So if you have some lambda expressions like {() -> new MyObject();} it can be written as MyObject::new. I think not all lambda expressions can be represented by using Method References.

I dont think it would be ideal to compare the lambda expression support in Java 8 with that of more mature Groovy or Scala support. This is the first step for Java to introduce lambda expressions so going forward we can expect to have more mature support for lambda expressions.

like image 38
MohamedSanaulla Avatar answered Sep 22 '22 03:09

MohamedSanaulla