I will start with an example. Here's the equivalent of List.fill for tuples as a macro in Scala 2.10:
import scala.language.experimental.macros import scala.reflect.macros.Context object TupleExample { def fill[A](arity: Int)(a: A): Product = macro fill_impl[A] def fill_impl[A](c: Context)(arity: c.Expr[Int])(a: c.Expr[A]) = { import c.universe._ arity.tree match { case Literal(Constant(n: Int)) if n < 23 => c.Expr( Apply( Select(Ident("Tuple" + n.toString), "apply"), List.fill(n)(a.tree) ) ) case _ => c.abort( c.enclosingPosition, "Desired arity must be a compile-time constant less than 23!" ) } } }
We can use this method as follows:
scala> TupleExample.fill(3)("hello") res0: (String, String, String) = (hello,hello,hello)
This guy is a strange bird in several ways. First, the arity argument must be a literal integer, since we must use it at compile time. In previous versions of Scala, there was no way (as far as I know) for the method to even say whether one of its arguments was a compilation literal or not.
Secondly, the Product return type is false - the static return type will include a specific type and an element type defined by arguments, as shown above.
So how can I document this thing? I did not expect Scaladoc support at the moment, but I would like to make sense of conventions or best practices (except that I am sure that the error messages at compile time are clear) that would make it work in a macro method - with its potentially strange requirements - less surprising for users of the Scala 2.10 library.
The most mature demonstrations of the new macro-system (for example, ScalaMock , Slick , the others listed here ) are still relatively not documented at the method level. Any examples or pointers will be appreciated, including other languages ββwith similar macro systems.
Travis Brown Dec 12 '12 at 13:22 2012-12-12 13:22
source share