Syntactic sugar for functional programming in Java
Published 2012-01-23I enjoyed functional programming in Scala with map, reduceLeft, and filter, etc. But I didn't like its slow compilation speed; on my setup, it was 15-20 seconds minimum even with the Fast Scala Compiler (FSC), dependency tracking, a warm cache, and one .scala file touched. And it wasn't much faster on Amazon Web Services' beefiest server. So I looked into how else I could do basic functional programming on the JVM. There appear to be three options:
- Compile with another language with JVM output: anything from JRuby to BGGA (a fork of Java).
- Use a functional library like lambdaj, adapting to its unusual style.
- Use anonymous classes extending interfaces such as Runnable.
I tried making the third option more palatable by writing a Java code preprocessor for syntactic sugar :-) So now I can write code like this:
List<Integer> positiveInts = Arrays.asList(new Integer[] { 1, 2, 3 }); List<Integer> negativeInts = MAP_LO_LO(positiveInts, Integer, Integer, { return -_; });
MAP_LO_LO is one of the many C preprocessor macro I created. In this case, the _LO_LO name is because it maps from a List of objects to a List of objects. Postfix-style naming is unfortunately necessary to support arrays and primitives like int, float, etc. When you run the cpp command on the above code, it expands to something like:
List<Integer> positiveInts = Arrays.asList(new Integer[] { 1, 2, 3 }); List<Integer> negativeInts = map(positiveInts, new Mapper<Integer, Integer>() { public Integer transform(Integer _) { return -_; } });
Hopefully that single example gave you an idea of its possibilities and limitations. I fleshed out the idea a bit and released it as the BlockSyntaxInJava project on Github. The basic advantages of my solution are:
- Unix users already have cpp installed
- The macro expansion isn't too complicated to debug
- You can ease into learning it gradually
The disadvantages are:
- This library is alpha and abandonware
- Windows users will have to download a cpp.exe
- Unconventional use of the C preprocessor could confuse people
- Anonymous classes don't conveniently express some use cases with checked exceptions or non-local control flow, as Neal Gafter points out.
Anyway, it was fun to create; maybe it will inspire you to use the C preprocessor for something.