說我有一個性狀Foo
我具有初始值i
到對象的成員宏接入其中宏被定義
val foo = new Foo(6) // class Foo(i: Int)
後來我所說的secondMethod
,在又調用實例化myMacro
foo.secondMethod(7) // def secondMethod(j: Int) = macro myMacro
那麼,myMacro
怎麼能找到i
(6)的初始值?
我沒有使用c.prefix
,c.eval(...)
等正常編譯反射成功,而是找到了2項目解決方案:
項目B:
object CompilationB {
def resultB(x: Int, y: Int) = macro resultB_impl
def resultB_impl(c: Context)(x: c.Expr[Int], y: c.Expr[Int]) =
c.universe.reify(x.splice * y.splice)
}
項目A(取決於項目B):
trait Foo {
val i: Int
// Pass through `i` to compilation B:
def apply(y: Int) = CompilationB.resultB(i, y)
}
object CompilationA {
def makeFoo(x: Int): Foo = macro makeFoo_impl
def makeFoo_impl(c: Context)(x: c.Expr[Int]): c.Expr[Foo] =
c.universe.reify(new Foo {val i = x.splice})
}
我們可以創建一個Foo
並設置i
值或者與正常實例化或像makeFoo
這樣的宏。第二種方法允許我們在第一次編譯時在編譯時自定義Foo
,然後在第二次編譯中進一步自定義對輸入的響應(本例中爲i
)!在某種程度上,我們得到了「meta-meta」功能(或「pataphysic」-capabilities ;-)
通常我們需要在範圍內有foo來反思i
(例如c.eval(...)) 。但是,通過保存Foo
對象內部i
值,我們就可以隨時訪問,我們可以實例Foo
任何地方:
object Test extends App {
import CompilationA._
// Normal instantiation
val foo1 = new Foo {val i = 7}
val r1 = foo1(6)
// Macro instantiation
val foo2 = makeFoo(7)
val r2 = foo2(6)
// "Curried" invocation
val r3 = makeFoo(6)(7)
println(s"Result 1 2 3: $r1 $r2 $r3")
assert((r1, r2, r3) ==(42, 42, 42))
}
我的問題
我能找到i
在我的例子宏沒有這雙編譯兩輪牛車?
另一個前綴爲http://stackoverflow.com/a/17028600/1296806的示例,請參閱此答案的結尾以進行自我回答:http://stackoverflow.com/a/12486993/1296806 –
好的,謝謝。只是標記了我自己的答案作爲答案:-) –
我其實也研究了你提到的其他答案。但是,我並沒有從這個例子中的樹解構建構中心理上跳躍到使用前綴作爲樹構建的基礎。那麼我嘗試了幾種組合,但不是'Select(c.prefix.tree,TermName(「i」))''。 –