Question

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?

Was it helpful?

Solution

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 = ""
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top