Posted by

brucechapman on November 28, 2007 at 8:00 PM PST

In javaposse 150 the guys were talking about something and veered off on a tangent talking about multiple return values and tuples and such like. Next up they talked about the closures JSR. That sparked a thought that maybe we could transform the multiple return values problem in order to solve it using closures.

In javaposse 150 the guys were talking about something and veered off on a tangent talking about multiple return values and tuples and such like. Next up they talked about the closures JSR. That sparked a thought that maybe we could transform the multiple return values problem in order to solve it using closures.

So **what if** instead of returning multiple values, a method returned void, but had another formal parameter which was a closure to receive the results of the method?

I've downloaded the closures prototype compiler (2007-11-20 version) and had a play with that idea. Now if it had been a complete disaster you wouldn't be reading this, because I wouldn't have blogged about it, but you are reading it so lets get on with it.

Here is a method to convert rectangular to polar coordinates and pass the results (r,theta) to a receiver closure.

` static void toPolar(double x, double y, {double, double => void } rThetaReceiver) {`

rThetaReceiver.invoke(Math.sqrt(x*x + y*y), Math.atan2(y, x));

}

And this is how you use it

` // test toPolar`

toPolar(3,4,{double r, double theta =>

System.out.format("3,4 = %f<%fRad%n",r,theta);

});

Here is the complete class with both converters, and a round trip test. Note how the round trip nests the closures.

`package closures.multireturn;`

/**

*

* @author bchapman

*/

public class RectangularToPolar {

static void toPolar(double x, double y, {double, double => void } rThetaReceiver) {

rThetaReceiver.invoke(Math.sqrt(x*x + y*y), Math.atan2(y, x));

}

static void toRectangular(double r, double theta, { double, double => void} xYReceiver) {

xYReceiver.invoke(r * Math.cos(theta), r * Math.sin(theta));

}

public static void main(String[] args) {

// test toPolar

toPolar(3,4,{double r, double theta =>

System.out.format("3,4 = %f<%fRad%n",r,theta);

});

// test toRectangular

toRectangular(5, Math.PI / 2, { double x, double y =>

System.out.format("5<90deg = %f,%f%n",x,y);

});

// test Round trip - toPolar and back to rectangular

toPolar(3,4,{double r, double theta =>

System.out.format("3,4 = %f<%fRad%n",r,theta);

toRectangular(r, theta, { double x, double y =>

System.out.format("%f<%fRad = %f,%f%n",r,theta,x,y);

});

});

}

}

And here's the output

`C:\projects\quickhacks\src>javac closures\multireturn\RectangularToPolar.java`

C:\projects\quickhacks\src>java closures.multireturn.RectangularToPolar

3,4 = 5.000000<0.927295Rad

5<90deg = 0.000000,5.000000

3,4 = 5.000000<0.927295Rad

5.000000<0.927295Rad = 3.000000,4.000000

This looks promising. I'll keep exploring.

One of the interesting things which I think this demonstrates is how closures are such a fundamental building block that they offer the potential of solving quite a few other *problems* that we've traditionally thought of as requiring specialist language changes. Maybe such solutions are not quite as nice as a specialist language change, but good enough that the advantage of not having *yet another language feature* outweighs the now small disadvantage of not having the *perfect* solution.