带准引号的可变长度"select" s



使用Scala的准引号,您可以轻松地构建选择树,如下所示:

> 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(".")}""",但运气不好。

有没有办法用准引号来支持这一点?或者在这种情况下,我只需要手动构建选择树吗?

我认为没有一种方法可以用准引号直接做到这一点。我确信任何类似tq"""${List("a","b","MyObj").mkString(".")}"""的东西都不会起作用。我对准引号的理解是,它们只是提取器和应用程序的糖。

然而,在这个想法的基础上,我们可以定义一个自定义提取器来执行您想要的操作。(顺便说一句,我相信有更好的方式来表达这一点,但你明白了…)

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)

正如您所看到的,在构造和提取时,将提取器嵌套在准引号的深处都没有问题。

相关内容

  • 没有找到相关文章

最新更新