函数式编程
什么是函数式编程
函数式编程(Functional Programming FP):编程范式之一,通常为面向过程编程、面向对象编程。
面向对象编程:把现实世界中的事物抽象成程序世界中的类和对象,通过封装、继承和多态演示事物之间的联系。
函数式编程:把现实世界中事物和事物间联系抽象到程序世界中,对运算过程抽象化。
程序本质:根据输入通过某种运算获得相应的输出
函数式一等公民
- 函数可以存储到变量中
- 函数作为返回值
- 函数作为参数
- 函数可以在程序运行的时候通过new Function() 构造一个新函数
高阶函数(Higher-orderfunction)
- 可以把函数作为参数传递给另一个函数
- 可以把函数作为另一个函数的返回结果
闭包
闭包:函数和其周围的状态(词法环境)引用在一起形成闭包
在另一个作用域中调用一个函数的内部函数并访问到该函数作用域中的成员
闭包本质:函数在执行的时候会放到一个执行栈上,当函数执行完毕之后会从执行栈上移除,但是堆上的作用域成员因为被外部引用不能释放,因此内部函数依然可以访问外部的函数成员。
**
纯函数
**
纯函数:相同的输入得到相同的输出,没有任何可观察的副作用。
纯函数的功能库:lodash(提供对数组、数字、字符串、对象、函数等操作的一些方法)
纯函数好处:
- 可缓存,因为相同的输入会得到相同的结果,所以可以把结果缓存
- 可测试:让测试更方便
- 并行处理:多线程并行操作共享内存数据可能会出现意外情况,纯函数不需要访问共享内存数据,并行环境下可以任意运行纯函数
副作用:
让一个函数变的不纯,如果函数内部依赖外部,无法保证相同的输出
来源:配置文件
数据库
获取用户输入
1.方法通用性下降,不适合扩展和可重用性。
2.副作用会给程序带来安全隐患和不确定性
3.尽可能控制在可控范围内发生。
柯里化(Haskell Brooks Curry)
柯里化:当一个函数有多个参数的时候,先传递一部分参数调用它(这部分参数以后永远不变)
返回一个新的函数接受剩余的参数,返回结果
lodash中的柯里化函数
_.curry()
- 柯里化给一个函数传递较少的参数,得到一个已经记住某些固定参数的新函数
- 对函数参数的‘缓存’ ,让函数变的更灵活,让函数的粒度更小
- 让多元函数转换成一元函数,组合使用函数产生更强大的功能
函数组合
函数组合概念:把多个函数,组合生成一个函数
纯函数和柯里化很容易写出洋葱代码
如果一个函数经过多个函数处理才能得到最终值,可以把中间过程函数合并成一个函数。
函数组合可以让我们把细粒度的函数重新组合生成一个新的函数
管道
函数组合默认是从右到左执行
lodash中的组合函数
lodash中组合函数flow()或者flowRight(),他们都可以组合多个函数
flow()是从左到右运行
flowRight()是从右到左运行,使用的更多一些
**
lodash和lodash/fp 中map区别
lodash中的map 返回三个参数
lodash/fp 中的map 返回一个参数
PointFree
**
pointFree:不需要指明处理的数据
只需要合成运算过程
需要定义一些辅助的基本运算函数
**
Functor(函子)
**
容器:包含值和值的变形关系(这个变形关系就是函数)
函子:是一个特殊的容器,通过一个普通的对象来实现,该对象具有map方法,map方法可以运行一个函数对值进行处理(变形关系)
MayBe函子
我们在编程的过程中可能会遇到很多错误,需要对这些错误做相应的处理
MayBe函子的作用就是可以对外部的空值情况做处理(控制副作用在允许的范围)
**
Either函子
**
Either两者中的任何一个,类似于if…else…的处理
异常会让函数变的不纯,Either函子可以用来做异常处理
IO函子
IO函子中的_value是一个函数,这里是把函数作为值来处理
IO函子可以把不纯的动作存储到_value中,延迟执行这个不纯的操作(惰性执行),包装当前的操作纯
把不纯的操作交给调用者来处理
Task异步执行
folktale一个标准的函数式编程库和lodash、ramda不同的是,他没有提供很多功能函数
只提供了一些函数式处理的操作,例如:compose、curry等,一些函子Task、Either、MayBe等
Pointed函子
Pointed函子是实现了of静态方法的函子
of方法是为了避免使用new来创建对象,更深层的含义是of方法用来把值放到上下文Context(把值放到容器中,使用map来处理值)
Monad(单子)
Monad函子是可以变扁的Pointed函子,IO(IO(x))
一个函子如果具有join和of两个方法并遵守一些定律就是一个Monad,
解决函数嵌套的问题