是否可以使用宏简化Scala方法参数声明?

时间:2013-01-30 14:07:02

标签: scala macros scala-2.10

通常使用明显的参数名称声明方法,例如

def myMethod(s: String, image: BufferedImage, mesh: Mesh) { ... }

参数名称对应于参数类型。

1)“s”通常用于String

2)“i”代表Int

3)一个名为classes(Mesh - > mesh)

的单词的小写类名

4)为长类名称(BufferedImage - > image)从类名小写最后一个单词

(当然,对于所有方法和参数都不方便。当然,有人会更喜欢其他规则......)

Scala宏旨在在代码中生成一些表达式。我想写一些特定的宏来转换为正确的Scala表达式,如下所示:

// "arguments interpolation" style
// like string interpolation
def myMethod s[String, BufferedImage, Mesh] 
{ /* code using vars "s", "image", "mesh" */ }

// or even better:
mydef myMethod[String, BufferedImage, Mesh] 
{ /* code using vars "s", "image", "mesh" */ }

有可能吗?

2 个答案:

答案 0 :(得分:2)

除了“为什么”(不是真的,你为什么要这样做?),答案是否定的,因为据我所知,宏不能(在当前状态下)生成方法或类型,只有表达式。

答案 1 :(得分:2)

目前这是不可能的,可能永远不会。宏不能引入自己的语法 - 它们必须通过有效的Scala代码表示(可以在编译时执行),并且它们也必须生成有效的Scala代码(更好的是有效的Scala AST)。

您显示的两个示例都不是有效的Scala代码,因此宏无法处理它们。然而,Macro Paradise的当前每晚构建包括无类型宏。它们允许编写Scala代码,这些代码在扩展后进行了类型检查,这意味着可以编写:

forM({i = 0; i < 10; i += 1}) {
  println(i)
}

请注意,第一个参数列表中的花括号是必需的,因为尽管代码在写入时没有进行类型检查,但它必须代表有效的Scala AST。

这个宏的实现如下:

def forM(header: _)(body: _) = macro __forM

def __forM(c: Context)(header: c.Tree)(body: c.Tree): c.Tree = {
  import c.universe._
  header match {
    case Block(
      List(
        Assign(Ident(TermName(name)), Literal(Constant(start))),
        Apply(Select(Ident(TermName(name2)), TermName(comparison)), List(Literal(Constant(end))))
      ),
      Apply(Select(Ident(TermName(name3)), TermName(incrementation)), List(Literal(Constant(inc))))
    ) =>

    // here one can generate the behavior of the loop
    // but omit full implementation for clarity now ...

  }
}

宏只需要一棵树,而不是已经有类型检查的表达式,在扩展后进行类型检查。方法调用本身需要两个参数列表,如果使用下划线,其参数类型可以在扩展阶段后延迟。

目前有一些documentation可用,但由于它是极端的测试版,很多事情可能会在未来发生变化。

使用类型宏可以编写如下内容:

object O extends M {
  // traverse the body of O to find what you want
}

type M(x: _) = macro __M

def __M(c: Context)(x: c.Tree): c.Tree = {
  // omit full implementation for clarity ...
}

这很好,以便延迟整个身体的类型检查,因为它可以让东西变凉......


目前还没有计划可以改变Scala语法的宏,这可能不是一个好主意。我不能说他们是否会在某一天发生,只有将来可以告诉我们。