Scala 这个def宏有什么问题?
免责声明:本规范不具有实际用途,仅用于教育目的 tl;dr:大部分只是我试图调试问题的结果,所以只有前3个片段是重要的 以下是宏定义:Scala 这个def宏有什么问题?,scala,macros,scala-macros,Scala,Macros,Scala Macros,免责声明:本规范不具有实际用途,仅用于教育目的 tl;dr:大部分只是我试图调试问题的结果,所以只有前3个片段是重要的 以下是宏定义: 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:
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))
整个项目可以找到(准备好运行)
此类调用失败,并显示以下消息:
[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)
。添加不声明新变量的行(或使用节点
)不会破坏行为,而
val nodePropK5 = tx(db) {
db.findNodesByLabelAndProperty(label, "k4", 100).iterator().next().getProperty("k5", 300)
val x = 5
x
}
结果显示相同的消息
另一件奇怪的事情:如果在宏扩展期间打印失败的块
,我会得到以下代码:
{
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
}
手动替换后,效果很好
我错过了什么?我可以随意假设这是一个编译器错误吗?当您看到这种错误时,首先要尝试的是取消正在宏输出中“重用”的类型检查代码。在这种情况下,更换以下部件:
val retVal = {
$block
}
与:
val retVal = {
${ c.untypecheck(block) }
}
我们应该做到这一点
请注意,在2.10中,
untypecheck
的等价物是resetAllAttrs
/resetLocalAttrs
。如果你搜索这些名称,你会发现很多关于你所看到的问题细节的讨论。对我来说,还有一件有趣的事情需要思考:为什么注释宏在没有“取消类型检查”的情况下工作?这是否与def宏已键入而注释宏未键入有关?是的,def宏的参数已进行类型检查,而宏注释的参数未进行类型检查。此外,有关非类型检查问题/解决方法的详细信息:。