Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ


Choose your language

InfoQ Homepage News Scala Adding Macros to the Language

Scala Adding Macros to the Language

Lire ce contenu en français

The team behind Scala is adding an experimental version of macros in the forthcoming release version 2.10. Scala macros provide an advanced form of compile-time meta-programming. The Scala macros website states:

Macros significantly simplify code analysis and code generation, which makes them a tool of choice for a multitude of real-world use cases. Scenarios that traditionally involve writing and maintaining boilerplate can be addressed with macros in concise and maintainable way. Therefore we believe that macros are a valuable asset to Scala programming language.

Scala's macros allow developers to create methods whose implementation is a syntax tree transformation. These are standard method definitions that are transparently transformed during compilation. A simple example is the assert method:

import scala.reflect.makro.Context
import language.experimental.macros
object Asserts {
   def assert(cond: Boolean, msg: Any) = macro Asserts.assertImpl
   def raise(msg: Any) = throw new AssertionError(msg)
   def assertImpl(c: Context)(cond: c.Expr[Boolean], msg: c.Expr[Any]): c.Expr[Unit] =
         if(assertionsEnabled) c.reify(if(!cond.splice) raise(msg.splice))
          else c.reify(())

The assert macro appears as a normal method in code. The implementation uses the macro method to delegate to a compiler extension. The compiler extension is the method assertImpl. assertImpl takes as parameters the current compilation context and the arguments to assert as syntax trees (Expr). These syntax trees are then used to generate a new syntax tree that is inserted at the location of the assert macro method call.

For the assert macro, a method call of assert(x != null, "X is null") will fill the cond variable with the syntax tree for x != null and the msg variable with the syntax tree for "X is null". The call to reify generates a new syntax tree of if(x != null) Asserts.raise("X is null") or (). This syntax tree replaces the orignal assert(x != null, "X is null") call.

reify and the self cleaning macro system are defined in more detail in the self cleaning macros proposal.

The addition of macros was considered dubious by some. In a blog post, entitled Scala Macros: "Oh God Why?", Jay Kreps states:

This was my reaction to the Scala macros proposal too. Not because there is anything necessarily bad about macros or the proposal, but just because - is this really the most critical thing?

Kreps proceeds to list a set of more important issues that include compilation speed, IDE support, documentation and compilation size.

Kreps was not alone in concerns. Ivan Todoroski writes, in a letter to the scala mailing list:

scala-macros look like a low-level hackish solution in search of a problem. They are complex to write, un-scalaish, difficult to debug, and will probably just add to Scala's image of "too much complex inscrutable magic". 

To which Martin Odersky, inventor of Scala, responds:

The intention of macros, and of Scala's language design in general, is to simplify things. We have already managed to replace code lifting by macros, and hopefully other features will follow. For instance, there was a strong push to somehow eliminate the implicit parameter in atomic { implicit transaction => ... } and several other related situations. With macros this is trivial. 

The debate over Scala macros has died down as the community waits for a look at the final implementation. A final release has not stopped the adventurous from trying a hand at macros. Several community macro based projects have sprouted, including:

  • Macrocosm - A library experimenting with practical use cases in macros.
  • Expecty - An adaptation of assert statements in Groovy's Spock into Scala.
  • Slick - An effort to bring LINQ-like database library. Slick can convert Scala syntax into database queries.
  • ScalaMock - A mock object testing library for Scala.

A list of other features coming in Scala 2.10 can be found in the 2.10.0-M4 release notes and include:

While the Scala 2.10.0 final release is rapidly approaching, the Scala team is asking for folks to experiment with the latest milestone release and provide feedback. You can download the latest milestone from here.

Rate this Article