【发布时间】:2013-05-03 07:06:54
【问题描述】:
我目前正在玩一些宏,无论如何这可能是个坏主意,但这是我的问题:
我有以下宏:
def using[A <: { def close(): Unit }, B](resource: A)(f: A => B) = macro usingImpl[A, B]
def usingImpl[A <: { def close(): Unit }, B](c: Context)(resource: c.Expr[A])(f: c.Expr[A => B]): c.Expr[B] = {
import c.universe._
f.tree match {
case Function(params, body) =>
//val ValDef(modifiers, name, tpt, _) = params.head
c.Expr[B](
Block(
List(
//ValDef(modifiers, name, tpt, resource.tree)
ValDef(params.head.symbol, resource.tree)
),
body
)
)
case _: Select =>
reify {
val res = resource.splice
try {
f.splice(res)
} finally {
res.close()
}
}
}
}
如果是Select,我只需调用该函数并关闭资源,就可以正常工作。但如果是Function,我想将参数值分配给资源并调用正文。当我使用 ValDef 的已弃用创建者时,需要 Symbol 和 Tree,一切正常。如果我使用的是注释掉的 4-args 创建器,我会收到编译器错误,指出值 x$1 不在范围内。当我查看两个版本生成的代码时,它看起来完全一样:
Expr[Int]({
<synthetic> val x$1: Test.Foo = new Test.this.Foo();
x$1.bar.+(23)
})
有没有办法简单地使用params.head 并分配一个值?感谢您的帮助!
编辑:
我这样调用宏:
object Test extends App {
import Macros._
class Foo {
def close() {}
def bar = 3
}
println(using(new Foo)(_.bar + 3))
}
正如我所说,如果我使用的是注释掉的版本,它会给我一个编译器错误,它会打印 AST,最后会显示以下消息:[error] symbol value x$1 does not exist in Test$delayedInit$body.apply
我使用的是 2.10.1。
【问题讨论】:
-
解构
params.head应该可以很好地工作——我无法重现您的错误(无论是 2.10.0 还是 2.10.1),实际上在未注释的版本中会出现编译器错误。你能发布你用来调用宏的代码吗? -
您一直在尝试将析构函数放入 Scala 中?好主意!
-
不,我试图解构一个闭包,以便在运行时它不会创建一个闭包。
标签: scala scala-macros