0

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(".")}"""でさえ、運がありません。

これを準引用符でサポートする方法はありますか? または、この場合、選択のツリーを手動で構築する必要がありますか?

4

1 に答える 1

1

準引用符でこれを完全に行う方法はないと思います。私は間違いなく何か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)

ご覧のとおり、構築時と抽出時の両方で、疑似引用符の奥深くに抽出子をネストしても問題はありません。

于 2016-07-19T17:53:06.180 に答える