函数式编程
ppt内容
今日问题:为什么要使用函数式编程?
1. 什么是函数式编程
一种编程范式,如何编程的方法论。一门语言一般会支持多种编程范式。
倡导利用若干简单的执行单元让计算结果不断渐进,逐层推导复杂的运算,而不是设计一个复杂的执行过程(主张声明式编程和编写抽象的代码)
例1:命令式vs声明式 例2:命令式的映射传入一个数字数组并返回一个每个数字都乘以2的新数组。
从例子上可以看出,相比于命令式的代码,函数式的代码趋向于更简洁,且抽象部分具有更高的复用性。
若在更为复杂的业务需求中,声明式编程,还拥有更高的可预读性。(命名规范很重要!!!)
命令式的代码,则是站在计算机的角度,更贴近于计算机的执行过程。
2. 函数式编程的好处
函数式编程的好处主要出自于以下特性
纯函数
柯里化
高阶函数
2.1 函数式编程--纯函数
纯函数:对于相同的输入,永远会得到相同的输出,而且没有任何可观察的副作用,也不依赖外部环境的状态的函数,叫做纯函数。
副作用:在计算结果的过程中,系统状态的一种变化,或者与外部世界进行的可观察的交互。比如修改了环境变量等。
例1:
数组的一些工具方法,改变了传入数组的均为非纯函数;concat这类没有修改入参的,也没有引用或者修改外部变量的方法,是纯函数。 例2:
纯函数带来的好处
测试无需考虑上下文,便于单元测试。因为纯函数的结果只与入参相关。
纯函数相较于非纯函数也有着更好的复用性。
纯函数适合写并发的执行代码。因为纯函数不会改变它的环境,这意味着我们根本不需要担心同步问题。
在我们的项目中,站在组件的角度,组件化的开发与函数式编程的纯函数理念是相似的。
2.2 函数式编程--柯里化(curry)
所谓"柯里化",就是把一个多参数的函数,转化为单参数函数。事实上柯里化也是一种闭包。
2.3函数式编程--高阶函数
定义:接受另一个函数作为其参数的函数称为高阶函数(Higher-Order-Function),或者说高阶函数是接受函数作为参数并且/或者返回函数作为输出的函数。一般而言,高阶函数通常用于抽象通用的问题,换句话说,高阶函数就是定义抽象。
节流(throtle)函数
总结
使用函数式编程的原因:
主要是我们的项目是组件化的,配合函数式编程的思想可以保证程序代码的健壮性,并提高组件的可复用性,降低开发成本。
看着高大上。。。
具体方案如下:
在编写函数的时候,尽量不修改全局变量和函数参数,保证函数的作用的内敛性,从而增加程序的健壮性。
简化我们的函数逻辑,每个函数专注一件事情,编写小而美的函数,采用函数嵌套来实现复杂的功能。提升可复用的粒度,提高代码可读性。
通过高阶函数抽象出通用的函数,提高代码的复用性,降低开发成本。
拓展内容
定义
"函数式编程"是一种"编程范式"(programming paradigm),也就是如何编写程序的方法论。它属于"结构化编程"的一种,相对于指令式编程更加强调程序执行的结果而非执行的过程,倡导利用若干简单的执行单元让计算结果不断渐进,逐层推导复杂的运算,而不是设计一个复杂的执行过程。简单来说,就是函数式编程关心类型(代数结构)之间的关系,命令式编程关心解决问题的步骤。
编程范式和编程语言之间的关系可能十分复杂,一个编程语言可以支持多种范式。 下面列举部分编程范式,作为参照:
指令式编程:是一种描述计算机所需作出的行为的编程典范。是面向计算机硬件的抽象,有变量(对应着存储单元),赋值语句(获取,存储指令),表达式(内存引用和算术运算)和控制语句(跳转指令),一句话,命令式程序就是一个冯诺依曼机的指令序列。
计算机的硬件工作一般都是指令式的。现在的大部分编程语言都是指令式的,同时拓展支持其他的一些编程范式。早期的指令式编程语言都是计算机本身的机械语言,指示非常简单,令硬件的运行更容易,却阻碍了复杂程序的设计。
优缺点:更贴近计算机执行逻辑,业务逻辑复杂时,可读性较低。
面向过程编程:是一种以过程为中心的编程典范。
以什么正在发生为主要目标进行编程,注重发生事件的顺序,不同于面向对象的是谁在受影响。与面向对象明显的不同就是没有封装、继承、类。面向过程是从上往下步步求精,所以面向过程最重要的是模块化的思想方法。
优缺点: 性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;面向过程的缺点:没有面向对象易维护、易复用、易扩展。
面向对象编程:是种具有对象概念的程序编程典范,同时也是一种程序开发的抽象方针。
其本质是以建立模型体现出来的抽象思维过程和面向对象的方法。特点是具有重用性、灵活性和扩展性。
面向对象的优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护;面向对象的缺点:性能比面向过程低。
Lambda表达式
“Lambda 表达式”(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。
特性
闭包和高阶函数
函数编程支持函数作为第一类对象,有时称为闭包或者仿函数(functor)对象。实质上,闭包是起函数的作用并可以像对象一样操作的对象。与此类似,FP 语言支持高阶函数。高阶函数可以用另一个函数(间接地,用一个表达式) 作为其输入参数,在某些情况下,它甚至返回一个函数作为其输出参数。这两种结构结合在一起使得可以用优雅的方式进行模块化编程,这是使用 FP 的最大好处。
函数是“一等公民”
可赋值给变量
可作为参数传递
可作为返回值
可在执行时声明
可以匿名的形式存在
可立即执行
惰性计算
在惰性计算中,表达式不是在绑定到变量时立即计算,而是在求值程序需要产生表达式的值时进行计算。
递归
用递归做为控制流程的机制。目前js中的for循环,while循环等,都存在对变量的反复赋值,所以并不是一个纯函数式编程的实现。
只用"表达式",不用"语句"
"表达式"(expression)是一个单纯的运算过程,总是有返回值;"语句"(statement)是执行某种操作,没有返回值。函数式编程要求,只使用表达式,不使用语句。也就是说,每一步都是单纯的运算,而且都有返回值。
没有"副作用"
指的是函数内部与外部互动(最典型的情况,就是修改全局变量的值),产生运算以外的其他结果。
不修改状态
函数式编程只是返回新的值,不修改系统变量。
引用透明性
函数程序通常还加强引用透明性,即如果提供同样的输入,那么函数总是返回同样的结果。这有助于验证正确性、简化算法,甚至有助于找出优化它的方法。
纯函数
对于相同的输入,永远会得到相同的输出,而且没有任何可观察的副作用,也不依赖外部环境的状态的函数,叫做纯函数。
优点
代码简洁,开发快速
接近自然语言,易于理解
更方便的代码管理
易于"并发编程"
代码的热升级
缺点
代码的简洁有时会带来额外的资源开销。
有些非函数式编程语言为求提升速度,不提供自动边界检查或自动垃圾回收等功能。
需要一定的学习成本。
总结
目前js开发中,完全的函数式编程是不符合实际的,但是我们可以借鉴它的思想。比如我们现在做的:
在编写函数的时候,尽量不修改全局变量和函数参数,保证函数的作用的内敛性,从而增加程序的健壮性。
比如简化我们的函数逻辑,编写小而美的函数,采用函数嵌套来实现复杂的功能。
毕竟在复杂的业务里面,代码的正确性、可靠性、稳定性,直接影响到是否需要996。
参考
Last updated
Was this helpful?