scala macros

Scala Macros: "no se puede crear TypeTag a partir de un tipo T que tenga parámetros de tipo no resueltos"



(1)

Estoy jugando con las nuevas macros Scalas y encontré esta esencia de akshaal . Como se ve, no lo entendí del todo. Dado el siguiente rasgo (el fieldsMacro es más o menos el mismo que en el ejemplo de akshaal)

case class Field[I <: AnyRef](name: String, get: I => Any) type Fields[I <: AnyRef] = List[Field[I]] trait FieldAccess { import FieldMacors._ import Field._ import language.experimental.macros def fields[T <: AnyRef]: Fields[T] = macro fieldsMacro[T] def field[T <: AnyRef](name: String): Fields[T] = fields[T].headOption <-- does not work! ^ } object FieldMacors { import language.experimental.macros import Field._ def fields[T <: AnyRef]: Fields[T] = macro fieldsMacro[T] /** * Get a list of fiels */ def fieldsMacro[T <: AnyRef: c.TypeTag](c: Context): c.Expr[Fields[T]] = { import c.universe._ val instanceT = c.typeOf[T] val fields = instanceT.members.filter(member => member.isTerm && !member.isMethod) // transform an iterable of expr in a expr of list. def foldIntoListExpr[T: c.TypeTag](exprs: Iterable[c.Expr[T]]): c.Expr[List[T]] = exprs.foldLeft(reify { Nil: List[T] }) { (accumExpr, expr) => reify { expr.splice :: accumExpr.splice } } val fieldAccessores = for (field <- fields) yield { val name = field.name.toString.trim // Why is there a space at the end of field name?! val nameExpr = c literal name // Construct expression (x : $I) => x.$name val getFunArgTree = ValDef(Modifiers(), newTermName("x"), TypeTree(instanceT), EmptyTree) val getFunBodyTree = Select(Ident(newTermName("x")), newTermName(name)) val getFunExpr = c.Expr[T => Any](Function(List(getFunArgTree), getFunBodyTree)) reify { Field[T](name = nameExpr.splice, get = getFunExpr.splice) } } foldIntoListExpr(fieldAccessores) } }

el compilador se queja sobre ''No se puede crear TypeTag desde un tipo T que tenga parámetros de tipo no resueltos''

¿Cómo logro obtener la T para la macro o debo implementar otra macro que use los camposMacro


T: TypeTag contexto T: TypeTag vinculado a un parámetro de tipo T significa que usted requiere que los argumentos de tipo proporcionados en lugar de este parámetro sean concretos (es decir, que no contengan referencias a parámetros de tipo no etiquetados o miembros de tipo abstracto). De lo contrario, se produce un error.

Ejemplos:

scala> val ru = scala.reflect.runtime.universe ru @ 6d657803: scala.reflect.api.JavaUniverse = scala.reflect.runtime.JavaUniverse@6d657803 scala> def foo[T: ru.TypeTag] = implicitly[ru.TypeTag[T]] foo: [T](implicit evidence$1: reflect.runtime.universe.TypeTag[T])reflect.runtime.universe.TypeTag[T] scala> foo[Int] res0 @ 7eeb8007: reflect.runtime.universe.TypeTag[Int] = TypeTag[Int] scala> foo[List[Int]] res1 @ 7d53ccbe: reflect.runtime.universe.TypeTag[List[Int]] = TypeTag[scala.List[Int]] scala> def bar[T] = foo[T] // T is not a concrete type here, hence the error <console>:26: error: No TypeTag available for T def bar[T] = foo[T] ^ scala> def bar[T] = foo[List[T]] // T being not concrete renders // the entire compound type not concrete <console>:26: error: No TypeTag available for List[T] def bar[T] = foo[List[T]] ^ scala> def bar[T: TypeTag] = foo[T] // to the contrast T is concrete here // because it''s bound by a concrete tag bound bar: [T](implicit evidence$1: reflect.runtime.universe.TypeTag[T])reflect.runtime.universe.TypeTag[T] scala> bar[Int] res2 @ 7eeb8007: reflect.runtime.universe.TypeTag[Int] = TypeTag[Int] scala> def bar[T: TypeTag] = foo[List[T]] bar: [T](implicit evidence$1: reflect.runtime.universe.TypeTag[T])reflect.runtime.universe.TypeTag[List[T]] scala> bar[Int] res3 @ 1a108c98: reflect.runtime.universe.TypeTag[List[Int]] = TypeTag[scala.List[Int]] scala> bar[List[Int]] res4 @ 76d5989c: reflect.runtime.universe.TypeTag[List[List[Int]]] = TypeTag[scala.List[scala.List[Int]]]

Es útil tener la noción de que los tipos concretos son aplicables en tiempo de compilación. Tener etiquetas de tipo concreto activadas por defecto es útil y también se describe en https://issues.scala-lang.org/browse/SI-5884 .

Sin embargo, como se ha visto a sí mismo, las etiquetas de tipo concreto en macros pueden ser una fuente de confusión, ya que normalmente las macros deberían funcionar tanto para tipos concretos como no concretos. Por lo tanto, siempre se debe usar c.AbsTypeTag en c.AbsTypeTag lugar. Debido a esta razón, ya no permitimos los c.TypeTag contexto de c.TypeTag en 2.10.0-M7: https://github.com/scala/scala/commit/788478d3ab .

Editar . En 2.10.0-RC1, se ha cambiado el nombre de WeakTypeTag a WeakTypeTag . Todo lo demás sobre las etiquetas de tipo sigue siendo el mismo.