gpt4 book ai didi

scala - 将传递的函数体拼接成宏重写的表达式

转载 作者:行者123 更新时间:2023-12-04 06:19:20 24 4
gpt4 key购买 nike

我正在使用 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 to 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在拼接函数体中引用。我收到以下错误:

ReplGlobal.abort: symbol value i does not exist in$line38.$read$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw. error: symbol value i does not exist in scala.reflect.internal.FatalError: symbol value i does not exist in $line38.$read$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw.



然后是一个相当大的堆栈跟踪,导致“放弃崩溃 session ”通知。

我不知道这是否是我的逻辑问题(您根本无法拼接引用封闭变量的函数体),或者它是否是新实现的错误。错误报告当然可以更好。我在 Repl 上运行它可能会加剧这种情况。

是否可以拆分一个函数,将主体与封闭项分开,然后重写它以便将逻辑直接拼接到结果树中?

最佳答案

如有疑问,resetAllAttrs :

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使所有符号正确。

关于scala - 将传递的函数体拼接成宏重写的表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20665778/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com