For a DSL I would like to be able to do something like:
object Creator {
def create[T](s :String) :Foo[T] = macro createImpl[T]
def createImpl[T](c :Context)(s :c.Expr[String]) : c.Expr[Foo[T]] = {
reify(new Foo[Any]())
}
}
My problem is to replace the Any in reify with something that will return the correctly parametrized version.
(above I use a string argument, but in the final version I plan to use the companion object of class T as a marker to know the argument-type of a Function1[T,Unit])
You need to:
a) write
new Foo[T]()instead ofnew Foo[Any]()(easy)b) pass in the macro a representation of type
T, namely, a value of typeAbsTypeTag[T], by declaring the parameterTusing a context bound:[T: c.AbsTypeTag].Here’s code which I tested in Scala 2.10.0-M7. Edit. In 2.10.0-RC1
AbsTypeTaghas been renamed toWeakTypeTag. Everything else about macros and type tags remains the same.Creator.scala:
MacroClient.scala:
Note that if you omit the type parameter, you will get a weird error:
You also write:
but if I get it right, this sounds like a bad idea. Instead of writing
Creator.create[T](otherArgs), the call syntax would be something likeCreator.create(T, otherArgs), not a big advantage (if any). But you can’t even get the latter syntax: ifclass Aandobject Aare companions, their types are not related: the first has typeA, the second has typeA.typewhereAis the companion object and not the type of classA.Update: how to get the
Creator create Foosyntax to work and return an instance ofFoo, if you have control overFoo.Since you ask about the
Anytype argument toreify, I assume you are asking about the type argument. That makes only sense if you want the static return type ofCreator.createto beTand notAny; otherwise, you should clarify your question.The problem here has little to do with macros.
Creator create Foopasses the objectFootoCreator.create, whose declaration needs to express, givenFoo.type, the typeFoothrough a type expression. Type expressions in Scala are quite limited – they can’t use reflection, for instance. But given a type, they can select its type members.This is limited since you need to alter the companion object, but I’m pretty sure you can’t do better. I know no way, in a type expression (what you can use in place of
Swhen declaring the return type ofcreate) of getting from a companion object to its associated class type in general, and I don’t think there’s one.Now, changing the above to use macros is straightforward: