Scala宏,它们在哪里使用?
我刚刚注意到Scala有宏,但我从未见过任何使用宏的代码。它们似乎也与C预处理器宏等有很大不同。通读宏的历史,看起来它们并没有提供任何以前在Scala中不可能提供的功能。在动机标题下,有一个宏启用的事项列表:Scala宏,它们在哪里使用?,scala,macros,metaprogramming,template-meta-programming,Scala,Macros,Metaprogramming,Template Meta Programming,我刚刚注意到Scala有宏,但我从未见过任何使用宏的代码。它们似乎也与C预处理器宏等有很大不同。通读宏的历史,看起来它们并没有提供任何以前在Scala中不可能提供的功能。在动机标题下,有一个宏启用的事项列表: 语言虚拟化(重载/重写 支持DSL深度嵌入的原始编程语言) 程序具体化(为程序提供检查其性能的方法 自己的代码) 自我优化(特定领域的自我应用) 基于程序具体化的优化) 算法程序 构造(生成代码,用它编写代码很枯燥) 由编程语言支持的抽象) 在菜单的后面,有实验性的宏功能,如类型宏、准
- 语言虚拟化(重载/重写 支持DSL深度嵌入的原始编程语言)
- 程序具体化(为程序提供检查其性能的方法 自己的代码)
- 自我优化(特定领域的自我应用) 基于程序具体化的优化)
- 算法程序 构造(生成代码,用它编写代码很枯燥) 由编程语言支持的抽象)
一个非常简单的例子。将项目编译到代码中的日期包括在内:
import java.util.Date
import reflect.macros.Context
import language.experimental.macros
object CompileTime {
def apply(): Date = macro applyImpl
def applyImpl(c: Context)(): c.Expr[Date] = {
import c.universe._
val now = System.currentTimeMillis() // this is executed during compilation!
val nowExpr = c.Expr[Long](Literal(Constant(now)))
val code = reify(new Date(nowExpr.splice))
c.Expr(code.tree)
}
}
使用该宏(以下代码必须与上述宏代码分开编译):
(如果运行多次,您会发现编译时间确实是恒定的)
因此,简而言之,宏提供了在任何以前的Scala版本中都不可用的功能。您可以使用宏执行其他操作无法执行的操作(通常可以使用运行时反射编写类似的操作,但宏是在编译时检查的) 但是,作为用户,您将越来越多地接触到包含宏的库,因为它们可以提供完全类型安全的强大构造。例如,可以使用宏实现case类中JSON的自动序列化,因为宏可以检查case类的类型,并构建正确的程序结构(AST)来读写该case类,而不会有运行时失败的危险 一些随机链接
object MacroTest extends App {
println(s"This project was compiled on ${CompileTime()}")
}