我刚刚注意到Scala有宏,但我从未见过任何使用它们的代码。它们似乎与C预处理器宏等完全不同。通过overview宏读取,看起来它们看起来不像以前在Scala中提供的任何东西。在动机标题下,有一个宏启用的事项列表:
- 语言虚拟化(overload / overriding语义) 原始编程语言,支持深度嵌入DSL),
- 计划具体化(为计划提供检查计划的方法) 自己的代码),
- 自我优化(特定领域的自我应用) 基于程序具体化的优化),
- 算法程序 构造(用代码编写繁琐的代码生成 编程语言支持的抽象)。
稍后在菜单中,有实验宏功能,例如类型宏,quasiquotes,无类型宏甚至更多。显然需要这个!
对于那些构建非常复杂的库并且对Scala有深刻理解的人来说,所有这些看起来都很不错。但是宏也为普通的Scala开发人员提供了一些东西吗?使用宏会使我的Scala代码更好吗?
答案 0 :(得分:20)
作为“普通”Scala开发人员,除非你有充分的理由,否则你很可能不会自己编写宏。
宏是一种编译时间元编程的方法,也就是说你编写程序。例如,def-macro是Scala 2.10的一部分,虽然仍然是“实验性的” - 看起来像常规方法,但无论何时在代码中调用该方法,编译器都会将该调用替换为隐藏在该方法后面的宏。将产生(一个新的代码片段)。
一个非常简单的例子。将项目编译的日期合并到代码中:
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)
}
}
使用该宏(以下代码必须从上面的宏代码单独编译 ):
object MacroTest extends App {
println(s"This project was compiled on ${CompileTime()}")
}
(如果多次运行,则会看到编译时间确实不变)
简而言之,宏提供了以前任何Scala版本中不的功能。您可以使用其他方法无法执行的操作(通常可以使用运行时反射编写类似的内容,但在编译时检查宏)。
作为用户,您将越来越多地接触到包含宏的库,因为它们可以提供完全类型安全的强大构造。例如,可以使用宏来实现案例类中JSON的自动序列化,因为宏可以检查案例类的类型并构建正确的程序结构(AST)来读取和写入案例类,而不会有运行时的危险故障。
一些随机链接