是否可以在scala宏中生成WeakTypeTag中的Apply?

Rog*_*ach 5 macros scala scala-2.10 scala-macros

我的WeakTypeTag宏中有一些类型,我想生成如下代码:

macroCreate[SomeObject] // => SomeObject(1)
Run Code Online (Sandbox Code Playgroud)

宏的定义将是这样的:

def macroCreate[A] = macro _macroCreate[A]
def _macroCreate[A](c: Context)(implicit wtt: c.WeakTypeTag[A]) = {
  c.Expr(Apply(Select(???, newTermName("apply")), List(c.literal(1).tree)))
}
Run Code Online (Sandbox Code Playgroud)

问题是,我如何得到Select给定的类型?

我可以使用一种解决方法,将类型转换为字符串,拆分"."然后创建一个Select字符串列表,但这看起来很糟糕.

是否可以Select直接从类型标签创建?

Tra*_*own 8

您可以获取伴随对象的符号,然后使用Universe的Ident(sym: Symbol): Ident工厂方法:

def macroCreate[A] = macro _macroCreate[A]

def _macroCreate[A](c: Context)(implicit wtt: c.WeakTypeTag[A]) = {
  import c.universe._

  c.Expr(
    Apply(
      Select(Ident(wtt.tpe.typeSymbol.companionSymbol), newTermName("apply")),
      c.literal(1).tree :: Nil
    )
  )
}
Run Code Online (Sandbox Code Playgroud)

然后:

scala> case class SomeObject(i: Int)
defined class SomeObject

scala> macroCreate[SomeObject]
res0: SomeObject = SomeObject(1)

scala> macroCreate[List[Int]]
res1: List[Int] = List(1)
Run Code Online (Sandbox Code Playgroud)

如果你的意思SomeObject是对象的类型(即,不是它的伴随类的类型),只需删除.companionSymbol上面的内容即可.

  • 我添加了一个小编辑(Select中的`newTermName`),因为scalac会抛出弃用警告.谢谢! (2认同)