The most horrible code I've ever written

When macros first showed up in Scala as an experimental language feature last year, many Scala developers responded with skepticism or distaste. They argued that macros were a distraction from work on more urgent problems with the language, that they would lead to even more complex and reader-unfriendly code, etc.

After a year and a half I think these arguments have less weight, as macros have proven extremely useful in a wide range of applications: string interpolation, serialization, type-level programming with singletons, numeric literals and faster loops, typed channels for actors, and so on. They’ve let me make many parts of my own code faster and safer in surprising ways.

This post is not about a useful application of macros. It’s inspired by a couple of questions on Stack Overflow today, and is an example of exactly the kind of thing macros should not ever be used for. But it’s Friday evening and I’m drinking beer in the office and I think this trick is pretty clever, so here we go.

Suppose we’ve got a Scala class with some mutable fields:

Also suppose we want to be able to write something like this:

Apparently some kind of syntax along these lines is possible in charming languages like Groovy and Visual Basic.

We can get close in Scala by adding a set method to Car:

And now we can write the following:

But suppose we’re not happy about those nine or ten extra characters, or that we don’t want the overhead of the extra function application. The problem is that color and speed don’t mean anything on their own. The argument to the macro needs to typecheck before the macro is expanded, so we can’t for example write a macro that would just prepend import car._ to the block (as proposed here).

If we had untyped macros, this would be easy, but they’ve been thrown out of paradise. We’re not completely out of luck with plain old def macros, though, since it’s possible to use them to introduce structural types with arbitrarily named and typed methods. This means we can bring some dummy methods into scope that have the same shape as the setters for Car. The compiler will see these methods when it typechecks the macro argument, and then our macro implementation can rewrite them to be calls to the real setters on Car.

Before we see my implementation of this horrible idea, let’s make the problem harder. Suppose we also have some methods on Car that change its state:

And want to be able to call these in our set block, like this:

This is so incredibly unpleasant I can’t believe I’m even writing it.

I’ll start with the easy part—the macro implementation of set. Note that I’m using quasiquotes, which are now available as a plugin in Scala 2.10. Without them this post would fill a small book.

Pretty straightforward. We just check the argument for assignments and try to rewrite them as assignments on the macro’s prefix.

Next for the messier part—building the instance of the structural type that will give us our dummy methods:

This wouldn’t be quite so bad if I could be bothered to figure out how to quasiquote multiple parameter lists; at the moment I can’t be.

Now we tie these pieces together:

And then define our Car class:

And we’re done:

It’s so ridiculous. I love it.