通常使用明显的参数名称声明方法,例如
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" */ }
有可能吗?
答案 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语法的宏,这可能不是一个好主意。我不能说他们是否会在某一天发生,只有将来可以告诉我们。