I'm trying to understand the following blog post, which discusses how to use macros to create a generic macro-based approach to convert case class objects to and from a map: http://blog.echo.sh/post/65955606729/exploring-scala-macros-map-to-case-class-conversion
Even though I read the entire post and another article on scala macros, I still do not fully understand how they work. Unfortunately, I'm receiving a couple of compile errors from the example code given in the blog post and am not sure why the errors are occurring nor how to resolve them. I'm reproducing the code below, preceded by the compile errors, for completeness (I annotated the code snippet with comments regarding the compile errors). Does anyone know why these compiler issues are occurring and how to resolve them?
-type mismatch; found : field.NameType required:
c.universe.TermName
-Can't unquote List[Nothing] with .., bottom type values often indicate programmer mistake
Here's the code:
import scala.reflect.macros.Context
import scala.language.experimental.macros
trait Mappable[T] {
def toMap(t: T): Map[String, Any]
def fromMap(map: Map[String, Any]): T
}
object Mappable {
implicit def materializeMappable[T]: Mappable[T] = macro materializeMappableImpl[T]
def materializeMappableImpl[T: c.WeakTypeTag](c: Context): c.Expr[Mappable[T]] = {
import c.universe._
val tpe = weakTypeOf[T]
val companion = tpe.typeSymbol.companionSymbol
val fields = tpe.declarations.collectFirst {
case m: MethodSymbol if m.isPrimaryConstructor ⇒ m
}.get.paramss.head
val (toMapParams, fromMapParams) = fields.map { field ⇒
val name = field.name
val decoded = name.decoded
val returnType = tpe.declaration(name).typeSignature
(q"$decoded → t.$name", q"map($decoded).asInstanceOf[$returnType]") // error 1
}.unzip
c.Expr[Mappable[T]] {
q"""
new Mappable[$tpe] {
def toMap(t: $tpe): Map[String, Any] = Map(..$toMapParams)
def fromMap(map: Map[String, Any]): $tpe = $companion(..$fromMapParams) // error 2
}
"""
}
}
}