J'essaie d'appeler une Shapeless
macro de l'intérieur d'un quasiquote
avec Scala
et je n'obtiens pas ce que j'aimerais obtenir.
Ma macro ne renvoie aucune erreur mais ne se développe pas Witness(fieldName)
dansWitness.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)"""
}
Voici ma Field
définition:
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)
}
}
Dans ce cas, l'implicite que je génère ressemble à:
implicit val implicitFieldname : Field[MyCaseClass, fieldWitness.`type`#T]{
override type fieldType = java.lang.String
}
S'il avait été défini en dehors d'un, quasiquote
il générerait quelque chose comme:
implicit val implicitFieldname : Field.Aux[MyCaseClass, Witness.Lt[String]#T, String] = ...
Peut-on faire quelque chose?
$in
(que je pense qu'il faudra utiliserConstantType
)?q"""implicit val $in : Field.Aux[$className, Witness.Lt[String]#T, String] = Field.apply[$className,$fieldType](Witness($fieldName), ($cc: $className) => $cc.$tn)"""
ConstantType
). Avez-vous un exemple de travail complet autour?Réponses:
Ceci est ma solution de travail en utilisant des annotations de macro à l'ancienne.
Cela peut être, à coup sûr, amélioré en utilisant de meilleures quasiquotes, mais mon objectif était de montrer quelque chose d'aussi propre que possible.
Il peut être utilisé comme:
Cela produit un
MyCaseClass
objet compagnon ayant desFields
implicits requis :Comme cela a déjà été souligné, sans un exemple de travail complet, il est assez difficile d'écrire une réponse exhaustive.
la source