使用宏在编译时创建类型良好的实例

时间:2013-04-03 06:00:38

标签: scala scala-macros

我希望能够使用基于某些类名的宏创建类型良好的实例。例如,我希望能够像这样创建一个Long实例:

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

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

实施将类似于:

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])
  }
}

我的问题是:

  • 如果类型取决于参数,我需要做什么让宏返回正确类型的对象?

  • 甚至可以使用Scala 2.10吗?

1 个答案:

答案 0 :(得分:1)

在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(()))
    })
  }
}

示例REPL会话,

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

scala> fromName("java.lang.String")
res1: String = ""