我正在尝试生成Tree
接受案例类值并在给定位置返回案例类参数值的函数。这对于提取私有参数的值很有用。
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)))
我还添加了以下依赖项:
scalaVersion := "2.11.8"
libraryDependencies ++= Seq(
"org.scala-lang" % "scala-reflect" % scalaVersion.value,
"org.scala-lang" % "scala-compiler" % scalaVersion.value
)
position
当None
案例类只有一个参数时。
我的解决方案有效,但我怎样才能摆脱tb.parse(s"...")
并用 quasiquote 替换它 q"..."
?
我试过了,但它失败了:
Don't know how to unquote here
[error] q"(a: $tpe) => $tpe.unapply(a).get$pos"
[error] ^
据我了解,我不能将一些在运行时构造并q"..."
在编译时解析的字符串插入到 quasiquote 中,这与tb.parse
. 我对吗?
像这样插值也安全s"(a: $tpe) => $tpe.unapply(a).get$pos"
吗?当使用q"..."
语法时,quasiquote 知道,$tpe
但Type
字符串插值会从中生成一个字符串。我不确定这是否会在更复杂和更具体的情况下始终有效。