Dan Stutzman

Syntactic sugar for functional programming in Java

Published 2012-01-23

I 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.