1

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

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

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

1) "s" 常用于String

2) "i" 表示 Int

3) 一个单词命名类的小写类名(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" */ }

是否可以?

4

2 回答 2

2

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

于 2013-01-30T14:20:33.590 回答
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 ...

  }
}

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

目前有一些可用的文档,但由于它是非常测试版,未来很多事情可能会发生变化。

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

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 ...
}

这很好,可以延迟整个身体的类型检查,因为它可以冷却东西......


目前还没有计划可以更改 Scalas 语法的宏,并且可能不是一个好主意。我不能说它们是否会在某一天发生,只有未来才能告诉我们这一点。

于 2013-01-30T16:32:19.440 回答