簡體   English   中英

Scala宏:構建一個匿名類

[英]Scala macros: constructing an anonymous class

我是Scala宏的新手,我正在嘗試編寫一個非常基本的DSL。

我有以下Scala類:

abstract class SpecialFunction {
  def apply(): Unit
}

和以下Scala宏:

def mImpl(c: Context)(bodyBlock: c.Expr[Unit]): c.Expr[X] =
  c.universe.reify {
    new X(new SpecialFunction {
      override def apply() {
        bodyBlock.splice
      }
    })
  }

def m(bodyBlock: Unit): X = macro mImpl

到現在為止還挺好。 例如,它允許我寫:

def example = m {
  println("Hello, world")
}

這歸結為:

def example = new X(new SpecialFunction {
  override def apply() {
    println("Hello, world")
  }
})

但是這個公式不允許我在這樣的“m塊”中有局部變量。 例如,我不能寫:

def example = m {
  val x = 7
  println(x.toString)
}

在編譯時我收到錯誤:

symbol value x does not exist in example

但是,我想要達到的目的是:

def example = new X(new SpecialFunction {
  override def apply() {
    val x = 7
    println(x.toString)
  }
})

(我想我理解為什么會這樣:子表達式在傳遞給宏之前被評估,因此對x的引用是無效的)。

所以我的問題是:我怎樣才能使上述工作成功? (我只是希望宏中定義的額外代碼在“m塊”中的代碼周圍“復制粘貼”,就像在C ++宏中一樣。)

任何幫助將不勝感激 :-)

您的輸出表達式保留對舊x符號的引用,但它應該是對新符號的引用。 因此,您可以通過從Context應用resetLocalAttrs來重置您要重用的樹中的所有垃圾引用。

怎么樣...?

def mImpl(c: Context)(bodyBlock: c.Expr[Unit]): c.Expr[X] =
  c.universe.reify {
    new X(new SpecialFunction {
      override def apply() {
        c.Expr[Unit](c.resetLocalAttrs(bodyBlock.tree)).splice
      }
    })
  }

在這個問題中 ,您可以閱讀Scala Macros的一個很好的解釋。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM