编写 Scala 2.10宏文档

我将从一个例子开始,这里有一个相当于 Scala 2.10中作为宏的元组的 List.fill:

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返回类型 都是谎言ー静态返回类型将包括由参数决定的特定数量和元素类型,如上所示。

那我要怎么记录下来?在这一点上我并不期待 Scaladoc 的支持,但是我希望能有一些约定或者最佳实践(不仅仅是确保编译时错误信息是清晰的) ,这些约定或者最佳实践能够使运行宏方法ーー带有其潜在的怪异需求ーー对于 Scala 2.10库的用户来说不那么令人惊讶。

新宏系统的最成熟的演示(例如,ScalaMock滑头和其他列出的 给你)在方法层面上仍然相对缺乏文档。任何例子或指针将受到赞赏,包括来自其他语言与类似的宏系统。

2369 次浏览

我认为记录这些最好的方法是使用示例代码,就像迈尔斯在他的实验 基于宏的分支中所做的那样。