Posts tagged with java
Here's how to get everything you need from closures today in Java, without waiting for the big foreheads to argue over how to make it nice and perfect.
You've almost certainly used something sort of closure-like when you've used the Runnable interface. You can for example create an anonymous subclass of Runnable and .run() it:
Runnable closure = new Runnable() {
void run() { System.out.println("Hello"); }};
closure.run(); // prints HelloIn particular in Java Thread class implements Runnable. You can do more interesting things, for example:
StringBuffer _myString = new StringBuffer("Hello");
// Java will only close around final variables because it's dumb
final StringBuffer foo = _myString;
Runnable closure = new Runnable() {
public void run() { System.out.println(foo); }
};
closure.run(); // prints HelloThis is why it's called a closure—the anonymous subclass Closes Around the variables in the scope in which it's defined. So, it has access here to myString. If you change _myString in the original context the closure will use the new value.
You can pass closures around, for example pass it to another method in another class, and it will still remain closed around the Original context. Like this:
public void anotherContext( Runnable closure ) {
StringBuffer foo = new StringBuffer("Goodbye");
closure.run(); // still prints Hello from its own context
}This is all available out of the box in Java, a little boring. It would be interesting if the closure could work on variables BOTH from its original context and that you pass into it at the same time. This can be done, but Runnable doesn't allow it, so we'll make our own Runnable:
// A general-purpose closure class that can receive and
// return values when you call it.
// This is an abstract class... override these functions for
// whatever kind of closure you need.
// If you call a non-overriden function, it will throw you.
public class SemaRunnable {
public void run() { throw new RuntimeException("Must override SemaRunnable.run()"); }
public Object run( Object param ) { throw new RuntimeException("Must override SemaRunnable.run()"); }
}
Now I can do a simple example (from the Wikipedia article):
SemaRunnable bestSellingBooks = new SemaRunnable() {
public Object run( Object thresholdObject ) {
int threshold = ((Integer)thresholdObject).intvalue();
// assume bookList is in the local context:
myBookList = bookList.booksWithSalesGreaterThan(threshold);
return myBookList;
}
};
// call books = bestSellingBooks.run( Integer(5000) );Here's a more complete example. In some code I'm working on, I need to pass an image—not just an image, but also the ability to get just a subImage of that image. I don't want them to have to know how to do image manipulation. Here is how I do it using closures:
SemaRunnable getSubImage = new SemaRunnable() {
public Object run( Object param ) {
int x = Array.getInt(param,0); // these four variables
int y = Array.getInt(param,1); // are coming in
int width = Array.getInt(param,2); // from the
int height = Array.getInt(param,3); // caller
// Now I will close on a method in my local context:
short[] subImg = dataForSubImage( x, y, width, height );
return subImg;
}
};
someObject.setClosureToBe(getSubImage);
...
// This method is being closed upon in the local context:
public short[] dataForSubImage( int x, int y, int width, int height ) {
...someObject in some completely different part of my code, gets the closure and calls it like this:
// completely different class, which received closure object
int [] subImageData = (int[])closure.run( new int [] {new_x, new_y, new_w, new_h} );
You don't have to call it closure. And you can pass as many params either way as you like, storing them in arrays, since array is an Object in java.
But... but... but..., people will say, why not create a class which does this, and import the class, and construct the class, and make calls on the class, it would do the same thing. They just answered their own question: it requires lots of LOCs.
And there's other good reasons. For example, let's say you have two versions of your function for different situations, you can simply swap them out of they are closures. The beauty of it is, the java compiler doesn't know or care what's happening, because everything is just SemaRunnable and Object. So it's not going to complain that a function or class name has changed. That means metaprogramming goodness. Sweet.
So, practical closures in Java. It may look a little unfamiliar at first, but once you know how to do it it's easy and can be really useful.
EXTRA SPECIAL BONUS: An implementation of the full monty, closure that takes a closure, makes a new closure from it, and returns that. I promised myself I'd go to bed early, but instead I stayed up and wrote you this code which is guaranteed to actually work, because I tried it. Try running it.
// By: Simon Woodside sbwoodside (a)(t) gmail (d)o(t) com
// See: http://simonwoodside.com/weblog/2009/7/7/a_little_bit_more_serious/
// To try this out:
// % javac Test.java && java Test
// Demonstration of how to do closures in Java
// In this case, |derivative| is a closure which approximates derivatives, and
// |sineDerivativeApproximator| approximates the derivative of ... you guessed it ... sine.
// It's hard to believe, given how much code there is, but in javascript this would be:
// function derivative(f, dx) {
// return function(x) {
// return (f(x + dx) - f(x)) / dx;
// };
// }
// (See http://en.wikipedia.org/wiki/Closure_(computer_science) )
import java.util.*;
import java.lang.reflect.*;
import java.lang.*;
public class Test {
public static void main (String args[]) {
System.out.println("Closures coming up!");
Test test = new Test();
test.go();
}
// SemaRunnable is a general-purpose closure class that can receive and
// return values when you call it.
// This is an abstract class... override these functions for
// whatever kind of closure you need.
// If you call a non-overriden function, it will throw you.
public class SemaRunnable {
public void run() { throw new RuntimeException("Must override SemaRunnable.run()"); }
public Object run( Object param ) { throw new RuntimeException("Must override SemaRunnable.run()"); }
}
void go() {
// Let's start with a really simple example.
// See my blog post for more details:
StringBuffer _myString = new StringBuffer("Hello");
final StringBuffer foo = _myString;
Runnable closure = new Runnable() {
public void run() { System.out.println(foo); }
};
closure.run(); // prints Hello
// Now let's do something more fun.
// A closure that receives a closure and returns a new closure.
// This is going to be wordy because Java Arrays and Number objects are TERRIBLE
// Return a function that approximates the derivative of f
// using an interval of dx, which should be appropriately small.
SemaRunnable derivative = new SemaRunnable() {
public Object run( Object params ) {
// params must be { SemaRunnable f, Float dx }
final SemaRunnable f = (SemaRunnable)Array.get(params,0); // get f
final float dx = ((Float)((Object[])params)[1]).floatValue(); // get dx
SemaRunnable approximator = new SemaRunnable() {
public Object run( Object xFloat ) {
float x = ((Float)xFloat).floatValue();
float fOfXPlusDx = ((Float)f.run( new Float(x + dx) )).floatValue();
float fOfX = ((Float)f.run( new Float(x) )).floatValue();
float answer = (fOfXPlusDx - fOfX) / dx;
return new Float(answer);
}
};
return approximator;
}
};
// Now create a closure that will simply return the sine(x):
SemaRunnable sineClosure = new SemaRunnable() {
public Object run( Object xFloat ) {
double sine = Math.sin( ((Float)xFloat).floatValue() );
return new Float(sine);
}
};
// And finally put it all together:
SemaRunnable sineDerivativeApproximator =
(SemaRunnable)derivative.run( new Object [] { sineClosure, new Float(0.001) } );
for( double x = 0.0; x<3.1416; x+=0.1 ) {
Float result = (Float)sineDerivativeApproximator.run(new Float(x));
System.out.println( "Sine(" + x + ") = " + result );
}
}
}
I ran out of time to demonstrate this, but you can also modify variables in the context from inside the closure, even though they are final, by creating a final array containing the variable, and then modifying the object contained in the array. It's not pretty but it works.
Hacking the java compiler: using anonymous subclasses as closures
Posted on July 10, 2008 at 11:17 PM
Categories: tech, code, java
UPDATE: new more comprehensive post on this subject: Closures with return values in Java.
In Java, closures/first-order functions are not a language feature. However, as everyone knows, you can effectively get a first-order function by using an anonymous subclass instead. Something like this:
class MyClosure {
void run() {} // override this
}
void doSomethingClosureLike() {
MyClosure closure = new MyClosure() { void run() { System.out.println("We're inside a closure!"); }};
runTheClosure(closure);
}
void runTheClosure(MyClosure closure) {
closure.run();
}
// will print We're inside a closure!
Anyway, it's simple enough, you pass the class instead of the function and there's a little extra verbage but it works!
Also you get closure-like functionality, because inside run() you can access variables from outwhere where you created it. E.g.:
void doSomethingCooler() {
final String myString = "Foo!";
MyClosure closure = new MyClosure() { void run() { System.out.println("The string is: " + myString); }};
runTheClosure(closure);
}
// will print The string is: Foo!
You can also access global variables that change over time, and the closure will use whatever is the current value WHEN THE CLOSURE RUNS.
There's just one small annoying thing, which is this particularly annoying compiler message:
local variable (WHATEVER) is accessed from within inner class; needs to be declared final
If you were do change myString to not be final, you'd get that error. Bummer. You could make myString a global variable and that would work, but that's stupid. There is a better way. Try this: UPDATE: This doesn't work, see new version at the bottom, thanks commenter the.d-stro.
void doSomethingCooler() {
String myString = "Foo!";
final String myStringFinal = myString;
myString.concat(" Bar!");
MyClosure closure = new MyClosure() { void run() { System.out.println("The string is:" + myStringFinal); }};
runTheClosure(closure);
}
// will print Foo! Bar!Now you can even change myString after you assign myStringFinal, because Java, although they say it doesn't use pointers, really does use pointers. I.e. it passes by reference. So, myStringFinal is actually just a reference to myString, and keeps pointing to it even when you change the contents of myString.
You can CHANGE it (like using concat()) but you CAN'T reassign it. That will break the pointers. It makes sense if you think about it—myString will have a new memory address, and myStringFinal will still be pointing to the old memory address (and the old string value). So, this won't work:
myString = "won't work"; // breaks myStringFinal
You can use this technique with any object (but not primitives like int).
UPDATE
The last source block is wrong because java Strings are immutable. Here's an example that will work as advertised:
void doSomethingCoolest() {
StringBuffer myString = new StringBuffer("Foo!");
final StringBuffer myStringFinal = myString;
myString.append(" Bar!");
MyClosure closure = new MyClosure() { void run() { System.out.println("The string is: " + myStringFinal); }};
runTheClosure(closure);
}
// will print The string is: Foo! Bar!