scala – 将传递的函数体拼接成宏重写的表达式
我正在玩
Scala 2.11的新宏功能.我想看看我是否可以进行以下重写:
forRange(0 to 10) { i => println(i) } // into val iter = (0 to 10).iterator while (iter.hasNext) { val i = iter.next println(i) } 我认为我对这个宏非常接近: def _forRange[A](c: BlackboxContext)(range: c.Expr[Range])(func: c.Expr[Int => A]): c.Expr[Unit] = { import c.universe._ val tree = func.tree match { case q"($i: $t) => $body" => q""" val iter = ${range}.iterator while (iter.hasNext) { val $i = iter.next $body } """ case _ => q"" } c.Expr(tree) } 当调用forRange(0到10)时,这会产生以下输出{i => println(i)}(至少,它是show函数在结果树上给我的东西): { val iter = scala.this.Predef.intWrapper(0).to(10).iterator; while$1(){ if (iter.hasNext) { { val i = iter.next; scala.this.Predef.println(i) }; while$1() } else () } } 看起来它应该可以工作,但我手动定义的val i和拼接函数体中引用的i之间存在冲突.我收到以下错误:
然后是一个相当大的堆栈跟踪,导致“被遗弃的崩溃会话”通知. 我无法判断这是否是我的逻辑问题(你根本无法在引用封闭变量的函数体中拼接),或者它是否是新实现的错误.错误报告肯定会更好.我在Repl上运行它可能会加剧这种情况. 是否可以拆分一个函数,将正文与封闭的术语分开,并重写它以便将逻辑直接拼接到结果树中? 解决方法
如有疑问,请重置AllAttrs:
import scala.language.experimental.macros import scala.reflect.macros.BlackboxContext def _forRange[A](c: BlackboxContext)(range: c.Expr[Range])( func: c.Expr[Int => A] ): c.Expr[Unit] = { import c.universe._ val tree = func.tree match { case q"($i: $t) => $body" => q""" val iter = ${range}.iterator while (iter.hasNext) { val $i = iter.next ${c.resetAllAttrs(body)} // The only line I've changed. } """ case _ => q"" } c.Expr(tree) } 然后: scala> def forRange[A](range: Range)(func: Int => A) = macro _forRange[A] defined term macro forRange: [A](range: Range)(func: Int => A)Unit scala> forRange(0 to 10) { i => println(i) } 0 1 2 3 4 5 6 7 8 9 10 一般来说,当你从一个地方抓住一棵树并将其放在其他地方时,可能需要使用resetAllAttrs来获得所有符号. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |