Scala中使用的宏是什么?使用函数无法完成的宏可以做些什么?
我想有一个好处是:
我还缺少其他任何优势吗?
答案 0 :(得分:1)
当它首先阻止你编写代码时,最常见的是宏的优势。
考虑play-json的情况。我可以定义一个case类,play-json格式化程序宏可以创建一些方法,使用我在类中定义的字段将我的CC转换为json和从json转换。
这里的关键是它参与了通常在运行时没有表示的源代码(变量的名称),它对它们进行编译时(类型安全!)反射创建特定的函数而不是使用运行时(不安全)反射。
答案 1 :(得分:1)
我同意Daenyth,宏对代码有一些适度但有用的好处。
为了论证,请考虑play-json 可以对生成代码所做的工作:
A)两个哑巴运行:
在" real"中使用更新后的定义运行
一开始非常简单,但很笨重,而且不是类型安全的
B)树和任务:以字符串形式读取def,但使用像Treehugger这样的运行时代码库将代码编写为树,并使用构建工具插件将代码生成任务添加到&#39 ;编译'
这使我们的类型安全性中途化,使用插件进行顺序编译至少提供了单次运行的错觉。
C)宏:使用实验性功能在编译时读取和写入树
宏是完全类型安全的,单一运行,并且在一次编译中完成所有操作意味着轻松修改生成的代码。
例如
假设我使用代码生成库将def printType
添加到case class Record(x: Int)
,并提供
case class Record(x: Int) {
def printType = println("Int")
}
现在说我想将自己的def goodbye
添加到课程中:
没有宏: 我可以
1)尝试将输出修改为
case class Record(x: Int) {
def printType = println("Int")
def goodbye = println("bye")
}
然后我遇到输出文件顶部打印的this is a generated file, DO NOT EDIT
,提醒我文件将被覆盖,所以我要么不得不去解决代码生成的麻烦,或
2)尝试修改输入 case class Record(x:Int){ def goodbye = println(" bye") } 但是代码库可能不会看到任意代码,所以我必须修改代码库本身。
使用宏: 如果代码库依赖于宏(并且库没有明确地处理类主体),我可以添加我的新的def输入
case class Record(x: Int) {
def goodbye = println("bye")
}
它只是有效;我的def在那里,生成的def也在那里。
case class Record(x: Int) {
def printType = println("Int")
def goodbye = println("bye")
}