[英]Scala macros: constructing an anonymous class
I am fairly new to Scala macros, and am trying to write a very basic DSL. 我是Scala宏的新手,我正在尝试编写一个非常基本的DSL。
I have the following Scala class: 我有以下Scala类:
abstract class SpecialFunction {
def apply(): Unit
}
and the following Scala macro: 和以下Scala宏:
def mImpl(c: Context)(bodyBlock: c.Expr[Unit]): c.Expr[X] =
c.universe.reify {
new X(new SpecialFunction {
override def apply() {
bodyBlock.splice
}
})
}
def m(bodyBlock: Unit): X = macro mImpl
So far so good. 到现在为止还挺好。 For example, it allows me to write:
例如,它允许我写:
def example = m {
println("Hello, world")
}
And this compiles down to: 这归结为:
def example = new X(new SpecialFunction {
override def apply() {
println("Hello, world")
}
})
But this formulation does not allow me to have local variables in such an "m block". 但是这个公式不允许我在这样的“m块”中有局部变量。 For example, I cannot write:
例如,我不能写:
def example = m {
val x = 7
println(x.toString)
}
At compile time I get the error: 在编译时我收到错误:
symbol value x does not exist in example
However, what I want to achieve is this: 但是,我想要达到的目的是:
def example = new X(new SpecialFunction {
override def apply() {
val x = 7
println(x.toString)
}
})
(I think I understand why this is the case: sub-expressions are evaluated before being passed to the macro, and thus the reference to x is invalid). (我想我理解为什么会这样:子表达式在传递给宏之前被评估,因此对x的引用是无效的)。
So my question is this: How can I get the above to work? 所以我的问题是:我怎样才能使上述工作成功? (I just want the extra code defined in the macro to be "copy-pasted" around the code in the "m block", like in a C++ macro.)
(我只是希望宏中定义的额外代码在“m块”中的代码周围“复制粘贴”,就像在C ++宏中一样。)
Any help would be greatly appreciated :-) 任何帮助将不胜感激 :-)
Your output expression is keeping a reference to the old x
symbol, but instead it should be a reference to a new one. 您的输出表达式保留对旧
x
符号的引用,但它应该是对新符号的引用。 Therefore, you can reset all the junk references in the tree you aim to reuse by applying resetLocalAttrs
from Context . 因此,您可以通过从Context应用
resetLocalAttrs
来重置您要重用的树中的所有垃圾引用。
How about...? 怎么样...?
def mImpl(c: Context)(bodyBlock: c.Expr[Unit]): c.Expr[X] =
c.universe.reify {
new X(new SpecialFunction {
override def apply() {
c.Expr[Unit](c.resetLocalAttrs(bodyBlock.tree)).splice
}
})
}
In this question , you can read a great explanation by the Scala Macros guy. 在这个问题中 ,您可以阅读Scala Macros的一个很好的解释。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.