Scala: Get type name without runtime reflection and without type instance

老子叫甜甜 提交于 2020-01-07 02:44:08

问题


I'd like to get the name of a type, as a String, without runtime reflection.

Using macros, and with an instance of the type, I can do it like this:

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

How can I do this without an instance of the type? I'd like a function signature like:

def typeName[A]: String

I can't use ClassTags because they don't provide the full type name, just the erased type. I also apparently can't use TypeTags because of thread safety issues.

EDIT: It appears this isn't possible in full generality (eg nested function calls). The accepted answer below states this in the comments.


回答1:


You can access tree that represents macro application: 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())
}

EDIT:

Another way to get the same, but maybe a little nicer:

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


来源:https://stackoverflow.com/questions/15649720/scala-get-type-name-without-runtime-reflection-and-without-type-instance

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!