Friday, September 16, 2005

Currying - A Very Interesting Use Of Generics

In bamboo-dht, a distributed java hashtable project, the main developer, Sean C. Rhea, advocates the use of Curries and Thunks (of LISP and ML). He wrote an interesting and valuable document, Async Tutorial, presenting a use of it. I will present the concept here shortly:

public interface Thunk1<T> { void run (T t ) ; }

Thunk1<Integer> intThunk = new Thunk1<Integer>() {
void run (Integer i ) { System.out.println( i ) ; }
}

public static <T> Runnable curry(final Thunk1<T> f ,final T t ) {
return new Runnable () { public void run ( ) { f.run ( t ) ; } } ;
}

Runnable print42 = curry( intThunk , new Integer ( 42 ) ) ;
print42.run ( ) ; //prints 42 to standard output


So it is a very clever way to have a callback in java. Very clever because you can declare your code to take only a run(), and pass any parameter in it by using a curry. It is very simple to use, even if the small framework around it can scare some people.

However neat the idea is, I am not sure it is practically useful. Sean C. Rhea used that because he did not want to use "unnecessary" instance variables. Ok, but the curry is still creating another instance (actually 2 but one could be static), is the overhead of a class instance without variables that much more than one with variables? And there is another way, without the Curry framework:

Runnable print42 = new Runnable({ public void run() {intThunk.run(new Integer(42));}});

print42.run();

This is actually exactly what the Curry framework would do behind the scenes. The Curry framework makes it a bit more elegant, but I am not sure if that's really more readable for most programmers. I would personally advise the traditional way, use instance variables.

Tags: ,

No comments :

Post a Comment