Scala微服务架构 二
三. Scala的Macro(宏)Scala Macros对scala函数库编程人员来说是一项不可或缺的编程工具,可以通过它来解决一些用普通编程或者类层次编程(type level programming)都无法解决的问题,这是因为Scala Macros可以直接对程序进行修改。 说到对程序进行修改,几个概念一定要先理解,"编译期"和"运行期",Java也有一个可以修改程序的功能,大家一定用过,就是反射.不是在运行期,编译器也不知道接下来会发生什么,会执行哪些代码(这就是==动态性==). 而scala是java的衍生语言,自然也有反射,而且它还有一种更高级的反射,就是编译时反射,它就是宏. 3.1 什么是宏?一般说来,宏是一种规则或模式,或称语法替换 ,用于说明某一特定输入(通常是字符串)如何根据预定义的规则转换成对应的输出(通常是字符串,或者是类,方法等)。这种替换在预编译时进行,称作宏展开。 通过上面的定义,感觉和C的宏概念差不多.但C的宏只不过是一段语法的替换,然而Scala的宏却可以通过表达式树控制一节代码(类,或者方法)的生成。获得了控制代码的执行顺序(见惰性计算和非限制函数)的能力,使得新创建的语法结构与语言内建的语法结构不可区分。 宏,从程序抽象的角度来看,可能不太容易调试和维护,但是能够很强大的固定我们的设计. 同时使用宏能够==大量==的减少样板代码.比如Scala的 3.2 宏出现的意义?
3.2.1 编译期元编程什么是元编程? 百度词条的一句话:
元编程是用来产生代码的程序,操纵代码的程序,在运行时创建和修改代码而非编程时,这种程序叫做元程序。而编写这种程序就叫做元编程。 所以,元编程技术在多种编程语言中都可以使用,但更多的还是被应用于动态语言中,因为动态语言提供了更多的在运行时将代码视为数据进行操纵的能力。 3.2.2 更完善的错误检查引自知乎https://www.zhihu.com/question/27685977/answer/38014170 首先思考一个问题:如果你的应用程序有bug,那么你希望在什么情况下发现呢?
而Scala的宏,就是可以将一些运行期才会出现的错误,在编译器暴露出来. 3.3 如何使用宏?Scala是如何使用宏的呢? 引用自https://www.cnblogs.com/tiger-xc/p/6112143.html graph TD A[编译器对程序进行类型验证] --> B{是否发现Macro标记} B --> |否| END[进行类型验证] B --> |是| C[使用Macro预编译解析程序] C --> D[生成语法树结构,AST,Abstract Syntax Tree] D --> E[使用AST替代需要类型验证的表达式] E --> END 明白了上面的流程之后,我们出个栗子: object modules { greeting("john") } object mmacros { def greeting(person: String): Unit = macro greetingMacro def greetingMacro(c: Context)(person: c.Expr[String]): c.Expr[Unit] = { import c.universe._ println("compiling greeting ...") val now = reify {new Date().toString} reify { println("Hello " + person.splice + ",the time is: " + new Date().toString) } } } 以上代码的执行逻辑如下: graph TD A[当编译器在编译modules遇到方法调用greeting时,会进行函数符号解析] --> B[调用mmacros里的greeting方法] B --> C{greeting方法是否为macro} C --> |否| END[函数调用] C --> |是| D[使用macro解析greetingMacro方法为AST] D --> E[将生成的AST替换到表达式greeting的调用处] E --> END
※. 本期语法糖※.1 implicit macor (隐式宏)官方文档 开局出个栗子 trait Showable[T] { def show(x: T): String } def show[T](x: T)(implicit s: Showable[T]) = s.show(x) implicit object IntShowable extends Showable[Int] { def show(x: Int) = x.toString } show(42) // return "42" show("42") // compilation error 可以调用成功 上面代码,乍一看还可以,但是如果扩展起来就不是很舒服了,如果要让 implicit object StringShowable extends Showable[String] { def show(x: String) = x } 可以看到,和上面的 ※.2 Macro Annotations ==> @compileTimeOnly("")官方文档 开局处个栗子 import scala.reflect.macros.Context import scala.language.experimental.macros import scala.annotation.StaticAnnotation import scala.annotation.compileTimeOnly @compileTimeOnly("enable macro paradise to expand macro annotations") class identity extends StaticAnnotation { def macroTransform(annottees: Any*): Any = macro ??? } 官网栗子,我们的代码也比较常见,继承了 主要说的是上面 @compileTimeOnly("enable macro paradise to expand macro annotations") 首先,这不是强制性的,即便不写,也会被编译器自动扩展上.但还是建议加上避免混乱. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- twitter-bootstrap-3 – 如何使用Bootstrap 3.0增加列之间的
- angularjs – 如何使用App Config中初始化的Angular Transl
- 命令行 – 如何从dos2unix,perl,tr和sed不存在的文件中删除
- bash Shell 总结《一》
- scala – 在不关闭系统本身的情况下停止系统中的所有actor?
- angularjs – Angular.js以编程方式将表单字段设置为dirty
- VIM没有突出显示PHP文件,突出显示其他文件
- angularjs – Angular-Ui-Router,嵌套的命名视图 – 我做错
- 用于解析/更新UNIX配置文件的API
- 使用Bootstrap打造特色进度条效果