0

実行時の反映なしで、タイプの名前を文字列として取得したいと思います。

マクロを使用し、そのタイプのインスタンスを使用すると、次のように実行できます。

def typeNameFromInstance[A](instance: A): String = 
  macro typeNameFromInstanceImplementation[A]

def typeNameFromInstanceImplementation[A](
  c: Context)(
    instance: c.Expr[A]): c.Expr[String] = {
  import c.universe._

  val name = instance.actualType.toString
  c.Expr[String](Literal(Constant(name)))
}

タイプのインスタンスなしでこれを行うにはどうすればよいですか?次のような関数シグネチャが欲しいのですが。

def typeName[A]: String

ClassTagsは完全な型名を提供せず、消去された型のみを提供するため、使用できません。また、スレッドセーフの問題のため、TypeTagsを使用できないようです。

編集:これは完全な一般性(例えば、入れ子関数呼び出し)では不可能であるようです。以下の受け入れられた答えはコメントでこれを述べています。

4

1 に答える 1

1

マクロアプリケーションを表すツリーにアクセスできます。c.macroApplication

def typeName[T]: String = macro typeName_impl[T]

def typeName_impl[T](c: Context): c.Expr[String] = {
  import c.universe._

  val TypeApply(_, List(typeTree)) = c.macroApplication
  c.literal(typeTree.toString())
}

編集:

同じようにする別の方法ですが、もう少し良いかもしれません:

def typeName[T]: String = macro typeName_impl[T]

def typeName_impl[T: c.WeakTypeTag](c: Context): c.Expr[String] = {
  import c.universe._

  c.literal(weakTypeOf[T].toString())
}
于 2013-03-27T00:22:02.367 に答える