0

以下の Scala quasiquote の 2 つの使用法で、 と の間result1で異なる出力が得られる理由を説明してくださいresult2。準引用符を使用して再現することは可能result3ですか? つまり、文字列の内容を解析して評価しますか?

import scala.tools.reflect.ToolBox
import scala.reflect.runtime.universe._

val miniSrc = "val lst = (1 to 5).toList ; val sum = lst.foldLeft(0)(_ + _); sum"

val tree1 = q"$miniSrc"
//tree1: reflect.runtime.universe.Tree = "val lst = (1 to 5).toList ; val sum = lst.foldLeft(0)(_ + _); sum"

val tree2 = q"val lst = (1 to 5).toList ; val sum = lst.foldLeft(0)(_ + _); sum"
//tree2: reflect.runtime.universe.Tree =
//{
//  val lst = 1.to(5).toList;
//  val sum = lst.foldLeft(0)(((x$1, x$2) => x$1.$plus(x$2)));
//  sum
//}

val tb = scala.reflect.runtime.currentMirror.mkToolBox()
val result1 = tb.eval(tree1)
//result1: Any = val lst = (1 to 5).toList ; val sum = lst.foldLeft(0)(_ + _); sum

val result2 = tb.eval(tree2)
//result2: Any = 15

val result3 = tb.eval(tb.parse(miniSrc))
//result3: Any = 15
4

1 に答える 1

3

以下の Scala quasiquote の 2 つの使用法で、 と の間result1で異なる出力が得られる理由を説明してくださいresult2

miniSrcはリテラルStringであり、 ではありませんTree。リテラルを別の にq"{$miniSrc}" リフト します。リフティングは、任意のコードを に解析するのではなく、ツリーまたは他のタイプをツリーに接合するだけです。したがって、はリテラルを含むです。miniSrcStringTreeTreetree1TreeString

この例は、リテラル文字列をツリーに持ち上げるのに解析が必要ない理由を十分に示しているはずです。

scala> val miniSrc = "abc"
miniSrc: String = abc

scala> val tree1 = q"$miniSrc"
tree1: reflect.runtime.universe.Tree = "abc"

tree2Treequasiquotes インターポレーターを使用して直接作成しているため、本質的に異なります。したがって、result1は単なるリテラル文字列ですがresult2、 内で実行されたコードの結果ですtree2

準引用符を使用して再現することは可能result3ですか? つまり、文字列の内容を解析して評価しますか?

いいえ、それが解析の目的です。任意のコードを文字列リテラルとして準引用符に持ち上げたい場合は、最初に解析する必要があります。Treeそれ以外の場合は、単なるリテラルになります。

scala> val tree1 = q"${tb.parse(miniSrc)}"
tree1: tb.u.Tree =
{
  val lst = 1.to(5).toList;
  val sum = lst.foldLeft(0)(((x$1, x$2) => x$1.$plus(x$2)));
  sum
}

マクロを使用する場合、マクロのContext. つまり、c.parse( を使用する代わりにToolBox)。

于 2016-09-24T23:20:02.867 に答える