0

您能否解释一下为什么下面 Scala quasiquote 的两种用法会在result1和之间给出不同的输出result2?是否可以result3使用 quasiquote 进行复制?即解析字符串内容并评估它?

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 的两种用法会在result1和之间给出不同的输出result2

miniSrc是文字String而不是Tree. q"{$miniSrc}" 升降机 miniSrc,一个字面String变成另一个Tree。Lifting 不会将任意代码解析为 a Tree,它只是将树或其他类型拼接成树。tree1因此是Tree包含文字的 a String

这个例子应该很好地说明为什么将文字字符串提升到树中不应该涉及任何解析:

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

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

tree2本质上是不同的,因为您是Tree直接使用 quasiquotes 插值器创建的。因此,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 回答