2

I want to be able to create well-typed instance with a macro based on some class names. For example I want to be able to create a Long instance like so:

def fromName[T](typeName: String) = macro FromNameMacro.impl[T]

// will typecheck ok
fromName("scala.Long") ==== 0L
// will not typecheck ok
fromName("scala.Long") ==== ""

The implementation would be something like:

import scala.reflect.macros.Context

object FromNameMacro {
  def impl[T: c.WeakTypeTag](c : Context)(klassName: c.Expr[String]): c.Expr[T] = {
    import c.{universe => u}; import u._
    val name = klassName.tree match { case Literal(Constant(n)) => n.toString }

    // of course this doesn't work...
    reify(this.getClass.getClassLoader.loadClass(name).newInstance.asInstanceOf[T])
  }
}

My questions are:

  • what do I need to do to have the macro return an object of the correct type, given that the type depends on a parameter?

  • is it even possible using Scala 2.10?

Eric
  • 15,494
  • 38
  • 61
  • It looks like what I want to do is only possible in macro-paradise: http://docs.scala-lang.org/overviews/macros/inference.html – Eric Apr 03 '13 at 06:36
  • Along with Miles' answer also see http://stackoverflow.com/questions/13669974/static-return-type-of-scala-macros – Eugene Burmako Apr 03 '13 at 20:41

1 Answers1

1

Having a macro return a result of the correct type is fairly straightforward in 2.10.x,

import scala.language.experimental.macros
import scala.reflect.macros.Context

object fromName {
  def apply(tpe: String): Any = macro fromNameImpl

  def fromNameImpl(c: Context)(tpe: c.Expr[String]): c.Expr[Any] = {
    import c.universe._

    c.Expr(tpe.tree match {
      case Literal(Constant("scala.Long")) => Literal(Constant(0L))
      case Literal(Constant("java.lang.String")) => Literal(Constant(""))
      case _ => Literal(Constant(()))
    })
  }
}

Sample REPL session,

scala> fromName("scala.Long")
res0: Long = 0

scala> fromName("java.lang.String")
res1: String = ""
Eric
  • 15,494
  • 38
  • 61
Miles Sabin
  • 23,015
  • 6
  • 61
  • 95
  • This works fine for me if I add that the return type of the macro is `c.Expr[Any]` (thanks Eugene for the pointer to the other SOF question, I read it yesterday but missed the point). Amazing... – Eric Apr 03 '13 at 23:29