记录Scala 2.10宏的文档

72

我来举个例子,在 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库的用户来说不那么令人惊讶。

新宏系统的最成熟演示(例如ScalaMockSlick和其他列在此处的)在方法级别上仍相对没有文档。任何例子或指针,包括其他具有类似宏系统的语言的例子,都将不胜感激。


12
关于ScalaMock,作为作者,我非常希望您能提出如何改进文档的建议。ScalaMock实际上是一种DSL,因此仅记录单个方法并没有太大意义。我已经尝试在这里将DSL文档化:http://scalamock.org/api/index.html#org.scalamock.package,并且有入门文档在这里:http://www.paulbutcher.com/2012/10/scalamock3-step-by-step/。有什么可以增加的吗? - Paul Butcher
2
@PaulButcher:我并不是要批评ScalaMock,我已经编辑了答案以使这一点更加清晰。在我尝试理解Scala的宏时,我发现阅读你的代码非常有用,而且我认为高级文档非常清晰明了。 - Travis Brown
8
没关系。但我非常感激任何改进的建议。请尽管提出。 - Paul Butcher
1个回答

1

我认为最好的记录方式是使用示例代码,就像Miles在他的实验性基于宏的分支中所做的那样。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接