2012-12-12 87 views
72

我將從一個例子開始。下面是List.fill元組等效爲斯卡拉2.10宏:記錄Scala 2.10宏

import scala.language.experimental.macros 
import scala.reflect.macros.Context 

object TupleExample { 
    def fill[A](arity: Int)(a: A): Product = macro fill_impl[A] 

    def fill_impl[A](c: Context)(arity: c.Expr[Int])(a: c.Expr[A]) = { 
    import c.universe._ 

    arity.tree match { 
     case Literal(Constant(n: Int)) if n < 23 => c.Expr(
     Apply(
      Select(Ident("Tuple" + n.toString), "apply"), 
      List.fill(n)(a.tree) 
     ) 
    ) 
     case _ => c.abort(
     c.enclosingPosition, 
     "Desired arity must be a compile-time constant less than 23!" 
    ) 
    } 
    } 
} 

我們可以按如下方式使用此方法:

scala> TupleExample.fill(3)("hello") 
res0: (String, String, String) = (hello,hello,hello) 

這傢伙是幾個方面的一個奇怪的鳥。首先,arity參數必須是一個字面整數,因爲我們需要在編譯時使用它。在以前的Scala版本中,對於一個方法來說,沒有辦法(據我所知)甚至不知道它的一個參數是否是編譯時的文字。

二,Product返回類型is a lie - 靜態返回類型將包含由參數確定的特定元素和元素類型,如上所示。

那麼我會如何記錄這件事?在這一點上我並不期待Scaladoc的支持,但我希望有一種習慣或最佳實踐(不僅僅是確保編譯時錯誤消息是清晰的),這會使其運行到宏觀方法中 - 潛在的離奇要求 - 對於Scala 2.10庫的用戶來說不會那麼令人驚訝。

新的宏系統(例如,ScalaMock,Slick,其他列出的here)的最成熟的演示在方法級別上仍然是相對未記錄的。任何示例或指針都會受到讚賞,包括來自其他語言的具有類似宏觀系統的示例或指針。

+12

關於ScalaMock,作爲作者,我非常感謝關於如何改進文檔的建議。 ScalaMock實際上是一個DSL,因此記錄單個方法並不一定意味着太多。我試圖在這裏整體記錄DSL:http://scalamock.org/api/index.html#org.scalamock.package,這裏有入門文檔:http://www.paulbutcher.com/2012/10/scalamock3-step-by-step /我可以添加哪些幫助? –

+2

@PaulButcher:我不是故意批評ScalaMock,而是編輯了更清晰的答案。我發現讀取代碼非常有用,因爲我一直在試圖理解Scala的宏,我認爲高級文檔非常清晰。 –

+8

沒有冒犯。但是,我肯定會感謝任何和所有我可以改進的方法。 –

回答

1

我認爲記錄這些文件的最好方法是使用示例代碼,因爲邁爾斯在他的無形的實驗macro based branch中已經做了。