在Scala編寫宏時,Quasiquotes簡化了許多事情。但是我注意到,每次在SBT中編譯時都會重新編譯包含quasiquotes的宏,即使宏實現和它的任何調用站點都沒有改變並且需要重新編譯。避免使用quasiquotes進行重新編譯
這似乎並沒有發生,如果quasiquotes中的代碼相當簡單,它似乎只在存在對另一個類的依賴時纔會發生。我注意到用「reify」重寫所有東西似乎解決了重新編譯問題,但我沒有設法在沒有quasiquotes的情況下重寫最後一部分...
我的宏通過在編譯期間創建包裝函數來避免反思啓動。
我有以下類:
object ExportedFunction {
def apply[R: Manifest](f: Function0[R], fd: FunctionDescription): ExportedExcelFunction = new ExcelFunction0[R] {
def apply: R = f()
val functionDescription = fd
}
def apply[T1: Manifest, R: Manifest](f: Function1[T1, R], fd: FunctionDescription): ExportedExcelFunction = new ExcelFunction1[T1, R] {
def apply(t1: T1): R = f(t1)
val functionDescription = fd
}
... and so on... until Function17...
}
我然後使用所描述的接口象這樣分析的object
和輸出任何成員函數:
def export(registrar: FunctionRegistrar,
root: Object,
<...more args...>) = macro exportImpl
def exportImpl(c: Context)(registrar: c.Expr[FunctionRegistrar],
root: c.Expr[Object],
<...>): c.Expr[Any] = {
import c.universe._
<... the following is simplified ...>
root.typeSignature.members.flatMap {
case x if x.isMethod =>
val method = x.asMethod
val callee = c.Expr(method))
val desc = q"""FunctionDescription(<...result from reflective lookup...>)"""
val export = q"ExportedFunction($callee _, $desc)"
q"$registrar.+=({$export})"
我可以重寫與第一和最後一行具體化但我沒有設法重寫第二行,我最好的辦法是用quasiquotes:
val export = reify {
...
ExportedFunction(c.Expr(q"""$callee _"""), desc)
...
}.tree
但是這會導致:
overloaded method value apply with alternatives... cannot be applied to (c.Expr[Nothing], c.universe.Expr[FunctionDescription])
我覺得編譯器缺少implicits,也許這段代碼的功能具有固定數量的參數只有工作,因爲它需要知道在宏觀編譯時如何該方法有很多爭論?然而,如果一切都寫作使用quasiquotes ...
非常感謝最新發布!它修復了這個問題;-) – gbasler
但是,項目中的宏在我們的項目中增加了編譯時間(即使沒有文件需要重新編譯)從37s到82s ... – gbasler
您能否提供更多詳細信息?看到一個需要37s編譯的sbt項目和另外一個需要82s編譯的項目會非常有幫助。 –