实例 | 记录一次函数式编程语法糖拆解过程

Posted 擎创夏洛克AIOps

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实例 | 记录一次函数式编程语法糖拆解过程相关的知识,希望对你有一定的参考价值。


使用Scala,不仅可以优雅地编写简洁的代码,又能减少很多低级错误;能快速进行开发,又能保证系统性能、团队协作和长期维护。

夏洛克ITOA系统,很多部分都使用Scala编写。相关的技术心得就很多                 



摘  要


Scala是一种集合了面向对象以及面向函数式的基于jvm的编程语言,所以编写scala代码,既可以完全类似java一样的风格,也可以写出基于函数式的天马行空的‘优雅’的代码,spark里面rdd相关的代码就是scala函数式编程的极致体现,真正做到了到最后一刻才会计算的延迟加载。


不过相比面向对象的风格,函数式编程风格的代码有时会难以理解,实际的执行顺序难以琢磨,下面是一个我最近看过的一个例子,简单记录一下。



解读过程


代码如下,入口在方法def imperativelyComplete,这个方法的主要目的是基于akka http的RequestContext进行封装,把当前http请求上下文传给其他地方进行处理,不过这个不是本文的重点,本文的重点是imperativelyComplete方法的定义,大家可以先自行观看几秒钟。



比较明显可以看出的是,这个方法的输入参数是一个函数(输入为ImperativeRequestContext类型,没有返回值),这种定义方法还是比较多见的,比如Loan Pattern


实例 | 记录一次函数式编程语法糖拆解过程


接着再看这个方法的方法体,会有一个类似类定义里面的self annotation的 ctx:RequestContext,看到这里有些同学可能就比较头晕了,这个ctx是哪来的?? 


别着急,都知道scala糖多,我们可以借助scalac这个工具,来看看去糖之后的样子,为了去除掉不必要的依赖,让scalac可以编译通过,我写了一个类似的例子(Test.scala):


实例 | 记录一次函数式编程语法糖拆解过程


执行scalar -Xprint:typer Test.scala

实例 | 记录一次函数式编程语法糖拆解过程

实例 | 记录一次函数式编程语法糖拆解过程

实例 | 记录一次函数式编程语法糖拆解过程

实例 | 记录一次函数式编程语法糖拆解过程

实例 | 记录一次函数式编程语法糖拆解过程


下面这个就是imperativelyComplete方法去糖之后的样子,可以看到这个方法的输入参数是一个函数,并且返回值也是一个函数,并且作为返回值的这个函数的输入参数为Req类型


实例 | 记录一次函数式编程语法糖拆解过程


看到这里就完全明白了。最开始例子里面的返回值也是一个函数:RequestContext => Future[RouteResult],只是目前的这种写法不是太明显,如果能像去糖后把返回值的结构清晰的定义出来,就一目了然了。如果我们看一下akka http库里面关于路由Route的定义,就会发现两者是一致的,所以在akka http的路由里面用imperativelyComplete这个方法,才可以编译通过。




结  论


函数式编程风格的代码有时确实比较难读懂,特别是在scala当中,结合implicit这种特性,就灵活度更大。如果一时看不懂,可以试着换种角度去理解(本文中我们在探寻ctx是哪来的,没想到它却是返回值的一部分),当然更推荐使用scalac这个工具来一探糖背后的组成。







夏洛克ITOA

Make Data Think

人工智能 | 机器学习 | IT运维





以上是关于实例 | 记录一次函数式编程语法糖拆解过程的主要内容,如果未能解决你的问题,请参考以下文章

Javascript 中的函数式编程

java 高级应用 - 函数式编程

5分钟学会函数式编程

多角度让你彻底明白yield语法糖的用法和原理及在C#函数式编程中的作用

Java没基础函数式编程——Stream API 中的收集器

Python3的语法糖和解析式