Java Closures? Or just functors? Or just confusion?

Java closures without lexical contexts? Nah, that's just plain functions, nor even functors. What the benefit, then?

Java "closures"

Well, I think I had to blog about this too!. It's somewhat fashionable, right? Let's try to see what the real benefits could be for a Swing developer, right?

If you think I'm wrong in any way I'd appreciate your comments.

Closures, the way I learned them.

As wikipedia clearly states a closure is a function that refers to variables in its local context. The "local context" is extremely important. If you don't have a local context then you just have a function, not a closure. Or, if that function is an object then you may refer to it as a functor. But I wouldn't use "closure" to refer to them. It's confusing.

Closures are cool in programming languages that support them. Scheme, for instance, supports closures:

; Define three variables
(define get-balance #f)
(define deposit #f)
(define withdraw #f)

; Build a new lexical environment with a "balance" variable, and bind previous
; three variables to closures in that environment
(let ((balance 0))
  (set! get-balance (lambda () balance))
  (set! deposit (lambda (amount) (set! balance (+ balance amount)) balance))
  (set! withdraw (lambda (amount) (set! balance (- balance amount)) balance)))

; Use the variables (now bound to closures).
(print (get-balance))
(print (deposit 100))
(print (withdraw 10))
(exit)

In the example above, the "balance" variable is just accesible to the closures, defined in their own local lexical environment (well, not really, but I think it's clear enough: "balance" is defined somewhere in a place accesible only to the lambda functions).

A (rough) Java equivalent could be:

class MyBalance
{
  private int balance = 0;
  public int getBalance() { return balance; }
  public int withdraw( int amount ) { return (balance-=amount); }
  public int deposit( int amount ) { return (balance+=amount); }
}

MyBalance x = new MyBalance();
System.out.println( x.getBalance() );
System.out.println( x.deposit( 100 ) );
System.out.println( x.withdraw( 10 ) );

So, as in the Scheme case, the "balance" variable is just accesible to the methods of the MyBalance class.

As far as I understand from the closures document there's no local context for the so called "closures". "Closures" may access the enclosing context, so they may access variables defined elsewhere in the enclosing context (without them being final) and that may prove cool.

But, you know, closures don't define a new local context (as far as I can tell) so I wouldn't call them closures. Otherwise you're just increasing confusion.

Let's call them, say, "functors".

Functors?

Functors in C++ are just cool. If you have ever used functors with C++ Standard Template Library, you'll probably agree with me. You may define C++ functors by using the operator overloading capabilities of C++, like this:

#include <iostream>
using namespace std;

class adder
{
  private:
    double sum;
  public:
    adder():sum(0) {}

    // This is where you define the () operator with one argument
    void operator()( double x ) { sum += x; }

    friend ostream& operator <<( ostream& os , const adder & a)
    {
      os << a.sum << endl;
      return os;
    }
};

int main( int argc, char ** argv )
{
  adder myadder;

  // HEY! myadder is an object but I'm using it
  // with a function syntax!!

  myadder(10);
  myadder(10);

  cout << myadder << endl;

  return 0;
}

Now, that's cool. You define a "()" operator and then your objects behave just like functions!

Ok, anyway, the idea of functors is that functors are objects. So, again, functors may have its own environment (the functor above contains a "sum" variable in its context). That's a great benefit of functors. You can use functors using a visitor pattern, and implement things like Ruby's "foreach" (available in the C++ STL library as well).

But, again, if the so called "Java closures" contain no lexical environment then those are not functors either.

Let's call them, say, functions.

Function types

Ah! There we go. The so called "Java closures" are just really "Java functions" or "Java function types".

Now, what's the real benefit of that?

Benefits. First try: Visitors?

If what you want to do is a "foreach" in a Collection, for instance (or any other type of visitor) then, why not just define a visitor interface? Something like, say:

public interface CollectionElementVisitor<t>
{
  public void visit( T anElement );
}

And, then, modify java.util.Collection to accept that sort of visitor:

public abstract class Collection<t>
{
  ...
  public void foreach( CollectionElementVisitor<t> aVisitor );
}

With that simple addition then "foreach" is just enabled in Java. We could finally do something like:

ArrayList<string> myList = new ArrayList<string>();
myList.add( "Hello" );
myList.add( "World" );

myList.foreach( new CollectionElementVisitor<string>()
  {
    public void visit( String anElement )
    {
      System.out.println( anElement );
    }
  } );

And that's crystal clear to Java people!

In fact, since we're using an anonymous class and not a "Java closure", we have now a lexical environment of our own, that we can use to number the strings, like this:

ArrayList<string> myList = new ArrayList<string>();
myList.add( "Hello" );
myList.add( "World" );

myList.foreach( new CollectionElementVisitor<string>()
  {
    int count=0;
    public void visit( String anElement )
    {
      System.out.println( (++count) + " " + anElement );
    }
  } );

And, as you see, I need no functions there. My simple interface behaves exactly as a function.

Benefits. Second try: currying?

Currying means transforming a function of several arguments to other of less arguments, one of which is fixed.

But, if the so called "Java closures" have no own lexical environment, how are you supposed to store that fixed argument? Currying is not feasible, then...

Benefits. For event handling?

Oh, for event handling in Swing? What's wrong with that, then? Removing a list of different listeners and using a single functor as a callback? Nah, that's asking for trouble, I think...

Benefits. For Swing?

TS-3802 "Applying Generics and Functors to Desktop Java Technology Programming" was one of the sessions I attended to at JavaOne 2004. I don't think I own a copy of that presentation anymore, and Google is unable to find a copy, either (I'd appreciate a copy of TS-3802).

That session talked about using generics and functors for Swing development. You know, it was interesting, but I never applied that.

Benefits. Shorter code?

I don't think "shorter code" or "fewer lines of code" is at all a meaningful metrics. No, I know that's contrary to some quality metrics, but I still defend my position. A friend of mine is happy to say you can build a web server in Perl with a single line. So what? Who is going to maintain that?

I'm of the opinion that the shorter the code the greater the confusion. And that seems to apply to "Java closures".

Summary: "Java closures" what for?

To summarize: I still can't see a real benefit of the so called "Java closures". If you know of any, that can't be resolved with the actual Java language, then I'd appreciate some examples.

All I can see is confusion.

So I'm closing closures, at the moment. ;-)

blog comments powered by Disqus