目前这是不可能的,而且可能永远不会。宏不能引入自己的语法——它们必须通过有效的 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 语法的宏,并且可能不是一个好主意。我不能说它们是否会在某一天发生,只有未来才能告诉我们这一点。