Estoy tratando de llamar a una Shapeless
macro desde dentro de un quasiquote
con Scala
y no obtengo lo que me gustaría obtener.
Mi macro no devuelve ningún error pero no se expande Witness(fieldName)
enWitness.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)"""
}
Aquí está mi Field
definición:
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)
}
}
En este caso, el implícito que genero se ve así:
implicit val implicitFieldname : Field[MyCaseClass, fieldWitness.`type`#T]{
override type fieldType = java.lang.String
}
Si se hubiera definido fuera de un quasiquote
, generaría algo como:
implicit val implicitFieldname : Field.Aux[MyCaseClass, Witness.Lt[String]#T, String] = ...
¿Hay algo que se pueda hacer?
$in
(que creo que requerirá usarConstantType
)?q"""implicit val $in : Field.Aux[$className, Witness.Lt[String]#T, String] = Field.apply[$className,$fieldType](Witness($fieldName), ($cc: $className) => $cc.$tn)"""
ConstantType
). ¿Tienes un ejemplo de trabajo completo?Respuestas:
Esta es mi solución de trabajo usando anotaciones macro de estilo antiguo.
Sin duda, se puede mejorar utilizando mejores cuasiquotes, pero mi objetivo era mostrar algo lo más limpio posible.
Se puede usar como:
Esto produce un
MyCaseClass
objeto complementario que requiereFields
implicits:Como ya se señaló, sin un ejemplo de trabajo completo, es bastante difícil escribir una respuesta exhaustiva.
fuente