记录Scala 2.10宏[关闭]


72

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

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

那么我将如何记录这件事呢?我现在不期望Scaladoc支持,但是我希望有一种约定或最佳做法(除了确保清楚编译时错误消息之外),它们可以运行到宏方法中-潜在的奇怪需求,对于Scala 2.10库的用户而言不足为奇。

新宏系统的最成熟的演示(例如ScalaMockSlick此处列出的其他示例)在方法级别上仍然没有记录。可以理解任何示例或指针,包括来自具有类似宏系统的其他语言的示例或指针。


12
关于ScalaMock,作为作者,我非常感谢您提出有关如何改进文档的建议。ScalaMock实际上是DSL,因此记录单个方法并不一定意味着太多。我已尝试在此处完整记录DSL:scalamock.org/api/index.html#org.scalamock.package,此处有入门文档:paulbutcher.com/2012/10/scalamock3-逐步我可以补充些什么呢?
Paul Butcher 2012年

2
@PaulButcher:我并不是要批评ScalaMock,我已经编辑了答案以使其更清楚。在尝试理解Scala的宏时,我发现阅读您的代码非常有用,而且我认为高级文档非常清楚。
特拉维斯·布朗

8
没有冒犯。但是,对于可以改进的方法,我将不胜感激。
保罗·布彻

Answers:


1

我认为记录这些内容的最佳方法是使用示例代码,正如Miles在他的基于Shapeless的实验性宏分支中所做的那样。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.