1
votes

Would anyone be so kind to post the equivalent Java code for a closure like this one (obtained using C#) with anonymous inner classes?

    public static Func<int, int> IncrementByN()
    {
        int n = 0; // n is local to the method

        Func<int, int> increment = delegate(int x)
        {
            n++;
            return x + n;
        };

        return increment;
    }
static void Main(string[] args)
   {

        var v = IncrementByN();
        Console.WriteLine(v(5)); // output 6
        Console.WriteLine(v(6)); // output 8
    }

Furthermore, can anyone explain how partial applications can be obtained if lexical closures are available and viceversa? For this second question, C# would be appreciated but it's your choice. Thanks so much.

3
Better not show him, he'll laugh at us Java people! - Marko Topolnik
For partial application in C#, check out my blog post about the topic: blogs.u2u.be/kris/post/2010/05/24/Lambda-Curry.aspx - Kris Vandermotten
Don't worry, I'm a C++ purist so I don't like C# either! - Eigendrea
I understand it's a bit puzzling, this code is nothing more than garbage. I needed an example to show how closures are obtained using C# delegates so the point of the code is the variable n is incremented outside its original scope - Eigendrea
@MarkoTopolnik Hopefully, when java does get its lambdas (September next year?) we will be able to shine a little more when answering these questions... - assylias

3 Answers

3
votes

There is no closure yet in Java. Lambda expressions are coming in java 8. However, the only issue with what you're trying to translate is that it has state, which not something that lamba expressions will support i don't think. Keep in mind, it's really just a shorthand so that you can easily implement single method interfaces. You can however still simulate this I believe:

final AtomicInteger n = new AtomicInteger(0);
IncrementByN v = (int x) -> x + n.incrementAndGet();
System.out.println(v.increment(5));
System.out.println(v.increment(6));

I have not tested this code though, it's just meant as an example of what might possibly work in java 8.

Think of the collections api. Let's say they have this interface:

public interface CollectionMapper<S,T> {
    public T map(S source);
}

And a method on java.util.Collection:

public interface Collection<K> {
  public <T> Collection<T> map(CollectionMapper<K,T> mapper);
}

Now, let's see that without closures:

Collection<Long> mapped = coll.map(new CollectionMapper<Foo,Long>() {
    public Long map(Foo foo) {
       return foo.getLong();
    }
}

Why not just write this:

Collection<Long> mapped = ...;
for (Foo foo : coll) {
    mapped.add(foo.getLong());
}

Much more concise right?

Now introduce lambdas:

Collection<Long> mapped = coll.map( (Foo foo) -> foo.getLong() );

See how much nicer the syntax is? And you can chain it too (we'll assume there's an interface to do filtering which which returns boolean values to determine whether to filter out a value or not):

 Collection<Long> mappedAndFiltered =
    coll.map( (Foo foo) -> foo.getLong() )
        .filter( (Long val) -> val.longValue() < 1000L );
0
votes

This code is equivalent I believe (at least it produces the desired output):

public class Test {

    static interface IncrementByN {
        int increment(int x);
    }

    public static void main(String[] args) throws InterruptedException {
        IncrementByN v = new IncrementByN() { //anonymous class
            int n = 0;

            @Override
            public int increment(int x) {
                n++;
                return x + n;
            }
        };
        System.out.println(v.increment(5)); // output 6
        System.out.println(v.increment(6)); // output 8
    }

}
0
votes

Assuming we have a generic function interface:

public interface Func<A, B> {
    B call A();
}

Then we can write it like this:

public class IncrementByN {

    public static Func<Integer, Integer> IncrementByN()
    {
        final int n_outer = 0; // n is local to the method

        Func<Integer, Integer> increment = new Func<Integer, Integer>() {
            int n = n_outer; // capture it into a non-final instance variable
                             // we can really just write int n = 0; here
            public Integer call(Integer x) {
                n++;
                return x + n;
            }
        };

        return increment;
    }
    public static void main(String[] args) {
        Func<Integer, Integer> v = IncrementByN();
        System.out.println(v.call(5)); // output 6
        System.out.println(v.call(6)); // output 8
    }
}

Some notes:

In your program, you capture the variable n by reference from the enclosing scope, and can modify that variable from the closure. In Java, you can only capture final variables (thus capture is only by value).

What I did here is capture the final variable from the outside, and then assign it into a non-final instance variable inside the anonymous class. This allows "passing info" into the closure and at the same time having it be assignable inside the closure. However, this information flow only works "one way" -- changes to n inside the closure is not reflected in the enclosing scope. This is appropriate for this example because that local variable in the method is not used again after being captured by the closure.

If, instead, you want to be able to pass information "both ways", i.e. have the closure also be able to change things in the enclosing scope, and vice versa, you will need to instead capture a mutable data structure, like an array, and then make changes to elements inside that. That is uglier, and is rarer to need to do.