如何在Quasiquote中使用无定形?

我试图从Scala内部的quasiquote调用一个Shapelessmacros,我没有得到我想要的。

我的macros不会返回任何错误,但不会将Witness(fieldName)扩展为Witness.Lt[String]

 val implicits = schema.fields.map { field => val fieldName:String = field.name val fieldType = TypeName(field.valueType.fullName) val in = TermName("implicitField"+fieldName) val tn = TermName(fieldName) val cc = TermName("cc") q"""implicit val $in = Field.apply[$className,$fieldType](Witness($fieldName), ($cc: $className) => $cc.$tn)""" } 

这是我的Field定义:

 sealed abstract class Field[CC, FieldName] { val fieldName: String type fieldType // How to extract this field def get(cc : CC) : fieldType } object Field { // fieldType is existencial in Field but parametric in Fied.Aux // used to explict constraints on fieldType type Aux[CC, FieldName, fieldType_] = Field[CC, FieldName] { type fieldType = fieldType_ } def apply[CC, fieldType_](fieldWitness : Witness.Lt[String], ext : CC => fieldType_) : Field.Aux[CC, fieldWitness.T, fieldType_] = new Field[CC, fieldWitness.T] { val fieldName : String = fieldWitness.value type fieldType = fieldType_ def get(cc : CC) : fieldType = ext(cc) } } 

在这种情况下隐式我生成如下所示:

 implicit val implicitFieldname : Field[MyCaseClass, fieldWitness.`type`#T]{ override type fieldType = java.lang.String } 

如果它是在quasiquote之外定义的quasiquote ,会产生如下的结果:

 implicit val implicitFieldname : Field.Aux[MyCaseClass, Witness.Lt[String]#T, String] = ... 

有什么可以做的吗?

这是我使用旧式macros注释的工作解决scheme。

 import scala.language.experimental.macros import scala.reflect.macros.blackbox.Context import scala.annotation.StaticAnnotation class fieldable extends StaticAnnotation { def macroTransform(annottees: Any*): Any = macro fieldableMacro.impl } object fieldableMacro { def impl(c: Context)(annottees: c.Expr[Any]*): c.Tree = { import c.universe._ annottees.map(_.tree) match { case (param @ q"case class $className(..$fields)") :: Nil => { val implicits = fields.collect { case field @ q"$mods val $tname: $tpt" => q""" implicit val $tname = Field.apply[$className,$tpt]( Witness(${tname.decodedName.toString}), _.$tname )""" }; q"$param; object ${className.toTermName} {..$implicits}" } } } } 

可以肯定的是,使用更好的quasiquotes改善,但我的目标是展示尽可能清洁。

它可以用作:

 @fieldable case class MyCaseClass(foo: String, bar: Int) 

这会生成一个MyCaseClass伴随对象,它具有必需的Fields implicits:

 implicit val foo = Field.apply[MyCaseClass, String](Witness("foo"), ((x$1) => x$1.foo)); implicit val bar = Field.apply[MyCaseClass, Int](Witness("bar"), ((x$2) => x$2.bar)); 

正如已经指出的那样,没有一个完整的实例,写出一个详尽的答案是相当困难的。