使用Scala的quasiquotes,您可以轻松地构建选择树,如下所示:
> tq"a.b.MyObj"
res: Select(Select(Ident(TermName("a")), TermName("b")), TermName("MyObj"))
我的问题是,如果要从(a,b,...等)中选择的事物列表是可变长度(因此在需要拼接的变量中),我该如何做?
我希望提升能够起作用(例如tq"""..${List("a","b","MyObj")}"""
但是它没有。或者甚至可能是tq"""${List("a","b","MyObj").mkString(".")}"""
,但没有运气。
有没有办法用quasiquotes支持这个?或者我只需要在这种情况下手动构建选择树?
答案 0 :(得分:1)
我认为没有办法用quasiquotes完全做到这一点。我绝对相信tq"""${List("a","b","MyObj").mkString(".")}"""
之类的东西都行不通。我对quasiquotes的理解是它们只是提取器的糖并且适用。
然而,基于这个想法,我们可以定义一个自定义提取器来做你想要的。 (顺便说一句,我确信有一种更好的表达方式,但你明白了......)
object SelectTermList {
def apply(arg0: String, args: List[String]): universe.Tree =
args.foldLeft(Ident(TermName(arg0)).asInstanceOf[universe.Tree])
((s,arg) => Select(s, TermName(arg)))
def unapply(t: universe.Tree): Option[(String,List[String])] = t match {
case Ident(TermName(arg0)) => Some((arg0, List()))
case Select(SelectTermList(arg0,args),TermName(arg)) =>
Some((arg0, args ++ List(arg)))
case _ => None
}
}
然后,您可以使用它来构造和提取a.b.MyObj
形式的表达式。
提取器测试:
scala> val SelectTermList(obj0,selectors0) = q"a.b.c.d.e.f.g.h"
obj0: String = a
selectors0: List[String] = List(b, c, d, e, f, g, h)
scala> val q"someObject.method(${SelectTermList(obj1,selectors1)})" = q"someObject.method(a.b.MyObj)"
obj1: String = a
selectors1: List[String] = List(b, MyObj)
相应的应用测试:
scala> SelectTermList(obj0,selectors0)
res: universe.Tree = a.b.c.d.e.f.g.h
scala> q"someObject.method(${SelectTermList(obj1,selectors1)})"
res: universe.Tree = someObject.method(a.b.MyObj)
正如您所看到的,在构造和提取时,将提取器嵌套在准引号内是没有问题的。