Quasiquote 解释树内容而不是将其视为文字
Quasiquote interpret tree content instead of taking as literal
你能解释一下为什么下面的 Scala quasiquote 的两种用法在 result1
和 result2
之间给出不同的输出吗?是否可以使用 quasiquote 重现 result3
?即解析字符串 content 并对其求值?
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, x) => x.$plus(x)));
// 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
Can you please explain why the two usages of Scala quasiquote below give different output between result1
and result2
?
miniSrc
是文字 String
而不是 Tree
。 q"{$miniSrc}"
提升 miniSrc
,一个文字String
变成另一个Tree
。 Lifting 不会将任意代码解析成Tree
,它只是将树或其他类型拼接成树。因此,tree1
是一个 Tree
,其中包含文字 String
.
这个例子应该足以说明为什么将文字字符串提升到树中不应该涉及任何解析:
scala> val miniSrc = "abc"
miniSrc: String = abc
scala> val tree1 = q"$miniSrc"
tree1: reflect.runtime.universe.Tree = "abc"
tree2
本质上是不同的,因为您是直接使用 quasiquotes 插值器创建 Tree
。因此,result1
只是一个文字字符串,而 result2
是 tree2
.
中某些执行代码的结果
Is it possible to reproduce result3
using quasiquotes? i.e parse a string content and evaluate it?
不,这就是解析的目的。如果您想将任意代码作为字符串文字提升到准引号中,您 必须 首先将其解析为 Tree
。否则,它将只是文字。
scala> val tree1 = q"${tb.parse(miniSrc)}"
tree1: tb.u.Tree =
{
val lst = 1.to(5).toList;
val sum = lst.foldLeft(0)(((x, x) => x.$plus(x)));
sum
}
并不是说在使用宏时,您可以使用宏的 Context
进行解析。即 c.parse
(而不是使用 ToolBox
)。
你能解释一下为什么下面的 Scala quasiquote 的两种用法在 result1
和 result2
之间给出不同的输出吗?是否可以使用 quasiquote 重现 result3
?即解析字符串 content 并对其求值?
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, x) => x.$plus(x)));
// 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
Can you please explain why the two usages of Scala quasiquote below give different output between
result1
andresult2
?
miniSrc
是文字 String
而不是 Tree
。 q"{$miniSrc}"
提升 miniSrc
,一个文字String
变成另一个Tree
。 Lifting 不会将任意代码解析成Tree
,它只是将树或其他类型拼接成树。因此,tree1
是一个 Tree
,其中包含文字 String
.
这个例子应该足以说明为什么将文字字符串提升到树中不应该涉及任何解析:
scala> val miniSrc = "abc"
miniSrc: String = abc
scala> val tree1 = q"$miniSrc"
tree1: reflect.runtime.universe.Tree = "abc"
tree2
本质上是不同的,因为您是直接使用 quasiquotes 插值器创建 Tree
。因此,result1
只是一个文字字符串,而 result2
是 tree2
.
Is it possible to reproduce
result3
using quasiquotes? i.e parse a string content and evaluate it?
不,这就是解析的目的。如果您想将任意代码作为字符串文字提升到准引号中,您 必须 首先将其解析为 Tree
。否则,它将只是文字。
scala> val tree1 = q"${tb.parse(miniSrc)}"
tree1: tb.u.Tree =
{
val lst = 1.to(5).toList;
val sum = lst.foldLeft(0)(((x, x) => x.$plus(x)));
sum
}
并不是说在使用宏时,您可以使用宏的 Context
进行解析。即 c.parse
(而不是使用 ToolBox
)。