I'm trying to generate Tree
for function that accepts case class value and returns value of case class parameter at given position. This is useful for extracting values of private parameters.
import reflect.runtime.currentMirror
import scala.reflect.runtime.universe._
import scala.tools.reflect.ToolBox
val tb = currentMirror.mkToolBox()
case class A(private val first: Int)
case class B(first: Int, private val second: Int)
def get(tpe: Type, position: Option[Int]): Tree = {
val pos = s"${position.map(p => s"._${p + 1}").getOrElse("")}"
tb.parse(s"(a: $tpe) => $tpe.unapply(a).get$pos")
}
println(tb.eval(get(typeOf[A], None)).asInstanceOf[(A) => Int](A(1)))
println(tb.eval(get(typeOf[B], Some(1))).asInstanceOf[(B) => Int](B(1, 2)))
Also I added following dependencies:
scalaVersion := "2.11.8"
libraryDependencies ++= Seq(
"org.scala-lang" % "scala-reflect" % scalaVersion.value,
"org.scala-lang" % "scala-compiler" % scalaVersion.value
)
position
is None
when case class has only one parameter.
My solution is working, but how can I get rid of tb.parse(s"...")
and replace it with quasiquote q"..."
?
I tried that but it fails with:
Don't know how to unquote here
[error] q"(a: $tpe) => $tpe.unapply(a).get$pos"
[error] ^
As I understood I can not insert into quasiquote some string that's constructed at runtime and q"..."
is parsed in compile time unlike tb.parse
. Am I right?
Also is it safe to interpolate like that s"(a: $tpe) => $tpe.unapply(a).get$pos"
? When using q"..."
syntax quasiquote knows that $tpe
is Type
but string interpolation makes a string from it. I'm not sure that this will work always and in more complex and specific cases.
Aucun commentaire:
Enregistrer un commentaire