2014-01-21 26 views
3

在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 ...

回答

6

從SBT問題的描述,我可以假設你使用2.10.x的宏觀天堂,並面臨https://github.com/scalamacros/paradise/issues/11。我打算在本週解決這個問題,所以修復應該很快到達。與此同時,您可以使用問題頁面上描述的解決方法。

至於實現問題,並非所有的quasiquotes都可以用reify來重寫。像你在這裏遇到的限制是我們將重點轉移到Scala 2.11中的quasiquotes的強大動力。

+0

非常感謝最新發布!它修復了這個問題;-) – gbasler

+0

但是,項目中的宏在我們的項目中增加了編譯時間(即使沒有文件需要重新編譯)從37s到82s ... – gbasler

+0

您能否提供更多詳細信息?看到一個需要37s編譯的sbt項目和另外一個需要82s編譯的項目會非常有幫助。 –

0

爲了記錄在案,這些SBT設置(升級到更新的版本)固定它:

... 
settings = Seq(
    libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value, 
    libraryDependencies += "org.scalamacros" % "quasiquotes" % "2.0.0-M3" cross CrossVersion.full, 
    autoCompilerPlugins := true, 
    addCompilerPlugin("org.scalamacros" % "paradise" % "2.0.0-M3" cross CrossVersion.full) 
)