【发布时间】:2014-08-22 14:42:09
【问题描述】:
免责声明:此代码没有实际用途,仅用于教育目的。
tl;dr:大部分只是我尝试调试问题的结果,所以只有前 3 个 sn-ps 很重要。
这里是宏定义:
def tx[T](ds: GraphDatabaseService)(block: => T): Option[T] =
macro txmacros.blockTxImpl[T]
这里是实现:
def blockTxImpl[T: c.WeakTypeTag](c: whitebox.Context)(ds: c.Tree)(block: c.Tree):
c.Tree = {
import c.universe._
q"""
val tx = $ds.beginTx()
val newRetVal = try {
val retVal = {
$block
}
tx.success()
Option(retVal)
} catch {
case _ : Throwable =>
tx.failure()
None
} finally {
tx.close()
}
newRetVal
"""
}
这就是它的名称:
val nodePropK5 = tx(db) {
// simplified for brevity
val node = db.find(label, "key", 100).iterator().next()
node.getProperty("k5", 300)
}
nodePropK5 should be (Some(200))
整个项目可以到https://github.com/cdshines/txMacro/找到(准备建一跑)。
此类调用失败并显示以下消息:
[error] symbol value node does not exist in MacroTest$$anonfun$3.apply$mcV$sp
[trace] Stack trace suppressed: run last core/test:compile for the full output.
[error] (core/test:compile) scala.reflect.internal.FatalError: symbol value node does not exist in MacroTest$$anonfun$3.apply$mcV$sp
但是,如果我将有问题的代码更改为
val nodePropK5 = tx(db) {
db.findNodesByLabelAndProperty(label, "k4", 100).iterator().next().getProperty("k5", 300)
}
如预期的那样,返回值为Some(300)。添加不声明新变量(或使用node)的行不会破坏行为,而
val nodePropK5 = tx(db) {
db.findNodesByLabelAndProperty(label, "k4", 100).iterator().next().getProperty("k5", 300)
val x = 5
x
}
产生相同的消息。
另一个奇怪的事情:如果我在宏扩展期间打印失败的block,我会得到以下代码:
{
val tx = MacroTest.this.db.beginTx();
val newRetVal = try {
val retVal = {
val node: org.neo4j.graphdb.Node = MacroTest.this.db.findNodesByLabelAndProperty(MacroTest.this.label, "k4", 100).iterator().next();
node.getProperty("k5", 300)
};
tx.success();
Option(retVal)
} catch {
case (_: Throwable) => {
tx.failure();
None
}
} finally tx.close();
newRetVal
}
手动替换,效果很好。
我在这里缺少什么?我可以假设这是一个编译器错误吗?
【问题讨论】:
标签: scala macros scala-macros