Scala 这个def宏有什么问题?

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:

免责声明:本规范不具有实际用途,仅用于教育目的

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: 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宏的参数已进行类型检查,而宏注释的参数未进行类型检查。此外,有关非类型检查问题/解决方法的详细信息:。