gpt4 book ai didi

Scala 宏 : constructing an anonymous class

转载 作者:行者123 更新时间:2023-12-02 03:47:27 24 4
gpt4 key购买 nike

我对 Scala 宏相当陌生,正在尝试编写一个非常基本的 DSL。

我有以下 Scala 类:

abstract class SpecialFunction {
def apply(): Unit
}

和下面的 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

到目前为止一切顺利。例如,它允许我写:

def example = m {
println("Hello, world")
}

这编译为:

def example = new X(new SpecialFunction {
override def apply() {
println("Hello, world")
}
})

但是这个公式不允许我在这样的“m block ”中有局部变量。例如,我不能写:

def example = m {
val x = 7
println(x.toString)
}

编译时出现错误:

symbol value x does not exist in example

然而,我想要实现的是:

def example = new X(new SpecialFunction {
override def apply() {
val x = 7
println(x.toString)
}
})

(我想我理解为什么会这样:子表达式在传递给宏之前被评估,因此对 x 的引用是无效的)。

所以我的问题是:我怎样才能让上面的工作起作用? (我只想将宏中定义的额外代码“复制粘贴”到“m block ”中的代码周围,就像在 C++ 宏中一样。)

任何帮助将不胜感激:-)

最佳答案

您的输出表达式保留对旧 x 符号的引用,但它应该是对新符号的引用。因此,您可以通过应用 Context 中的 resetLocalAttrs 来重置您打算重用的树中的所有垃圾引用。 .

怎么样...?

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
}
})
}

在此question ,您可以阅读 Scala Macros 专家的精彩解释。

关于Scala 宏 : constructing an anonymous class,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16067227/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com