Is static metaprogramming possible in Java?


Take a look at Clojure. It's a LISP with Macros (meta-programming) that runs on the JVM and is very interoperable with Java.


I am a fan of static metaprogramming in C++. I know Java now has generics. Does this mean that static metaprogramming (i.e., compile-time program execution) is possible in Java? If so, can anyone recommend any good resources where one can learn more about it?

Best introduction to C++ template metaprogramming?

[Answering my own question]

The best introductions I've found so far are chapter 10, "Static Metaprogramming in C++" from Generative Programming, Methods, Tools, and Applications by Krzysztof Czarnecki and Ulrich W. Eisenecker, ISBN-13: 9780201309775; and chapter 17, "Metaprograms" of C++ Templates: The Complete Guide by David Vandevoorder and Nicolai M. Josuttis, ISBN-13: 9780201734843.

alt text alt text alt text alt text

Todd Veldhuizen has an excellent tutorial here.

A good resource for C++ programming in general is Modern C++ Design by Andrei Alexandrescu, ISBN-13: 9780201704310. This book mixes a bit of metaprogramming with other template techniques. For metaprogramming in particular, see sections 2.1 "Compile-Time Assertions", 2.4 "Mapping Integral Constants to Types", 2.6 "Type Selection", 2.7 "Detecting Convertibility and Inheritance at Compile Time", 2.9 "NullType and EmptyType" and 2.10 "Type Traits".

The best intermediate/advanced resource I've found is C++ Template Metaprogramming by David Abrahams and Aleksey Gurtovoy, ISBN-13: 9780321227256

If you'd prefer just one book, get C++ Templates: The Complete Guide since it is also the definitive reference for templates in general.

Modern C++ Design, a brilliant book and design pattern framework by Alexandrescu. Word of warning, after reading this book I stopped doing C++ and thought "What the heck, I can just pick a better language and get it for free".

let me list a few important details about how metaprogramming works in lisp (or scheme, or slate, or pick your favorite "dynamic" language):

  • when doing metaprogramming in lisp you don't have to deal with two languages. the meta level code is written in the same language as the object level code it generates. metaprogramming is not limited to two levels, and it's easier on the brain, too.
  • in lisp you have the compiler available at runtime. in fact the compile-time/run-time distinction feels very artificial there and is very much subject to where you place your point of view. in lisp with a mere function call you can compile functions to machine instructions that you can use from then on as first class objects; i.e. they can be unnamed functions that you can keep in a local variable, or a global hashtable, etc...
  • macros in lisp are very simple: a bunch of functions stuffed in a hashtable and given to the compiler. for each form the compiler is about to compile, it consults that hashtable. if it finds a function then calls it at compile-time with the original form, and in place of the original form it compiles the form this function returns. (modulo some non-important details) so lisp macros are basically plugins for the compiler.
  • writing a lisp function in lisp that evaluates lisp code is about two pages of code (this is usually called eval). in such a function you have all the power to introduce whatever new rules you want on the meta level. (making it run fast is going to take some effort though... about the same as bootstrapping a new language... :)

random examples of what you can implement as a user library using lisp metaprogramming (these are actual examples of common lisp libraries):

  • extend the language with delimited continuations (hu.dwim.delico)
  • implement a js-to-lisp-rpc macro that you can use in javascript (which is generated from lisp). it expands into a mixture of js/lisp code that automatically posts (in the http request) all the referenced local variables, decodes them on the server side, runs the lisp code body on the server, and returns back the return value to the javascript side.
  • add prolog like backtracking to the language that very seamlessly integrates with "normal" lisp code (see screamer)
  • an XML templating extension to common lisp (includes an example of reader macros that are plugins for the lisp parser)
  • a ton of small DSL's, like loop or iterate for easy looping

Java code transform at compile time

I think you could try the same technique used in Project Lombok

It's approximately explained by the authors in this interview:

What's going on under the hood? I.e., how does an annotation result in the boilerplate ending up in the bytecode?

Reinier: The annotation processor API only lets you create new files, it does not let you modify the file that has the annotation inside of it. Which is what Lombok does, so Lombok does not use the annotation processor API.

Instead, Lombok uses the annotation processor API only as a mechanism to inject itself into the compilation process. All annotation processors are initialized early in the compilation process, and Lombok modifies javac when it is initialized as an annotation processor. We change only one thing: The AST (the raw source code, parsed into a tree form) is first handed off to Lombok, which generates whatever needs to be generated, before javac continues.

and in How does lombok work?

It's also possible to extend Project Lombok to your needs

If the C preprocessor would suffice, I did just manage to get it working with Eclipse in Windows. It only works on Juno though.