Open zlx362211854 opened 5 years ago
函数式编程的核心思想就是:申明式编程(Declarative programming)
。
与命令式编程不一样,不用去关心是怎么实现的,而关心实现了什么,比较典型的申明式编程: HTML
,JSX
等。
以画只猫为例子:
// 画猫
drawCat(
// 画头
drawHead,
// 画身体
drawBody,
// 画尾巴
drawTail,
)(blankPaper) // 传入一张白纸
drawCat 接收一张白纸,drawHead 在白纸上画头,然后把画有头的白纸传给 drawBody,画好身体后,又传给 drawTail。
很好的阅读性:
整个代码看起来就像读记述文一样,很容易就明白这段代码做了什么。具体复杂的实现,都封装到了drawHead,drawBody,drawTail这个三个纯函数里面。
非常灵活扩展性和复用性:
drawHead, drawBody, drawTail,都是纯函数,没有任何副作用,可以用 drawCat 随意组合。 如果不想要尾巴,想给猫咪画个帽子,直接删除 drawTail 这个方法,再加一个 drawHat 的纯函数。
// 画猫
drawCat(
// 画头
drawHead,
// 画身体
drawBody,
// 画尾巴
// drawTail,
// 画帽子
drawHat,
)(blankPaper) // 传入一张白纸
实现函数式编程的三个关键就是:纯函数
,组合函数
,柯里化
相同的输入永远得到相同的输出,也就是没有任何副作用。
drawCat 就是一个组合函数,将多个纯函数组装起来,分别执行,第一个纯函数执行返回的结果,是第二个纯函数的输入参数,以此类推。最终得到一张画了猫的白纸。
react-redux
的 combineReducer
就是一个非常典型的组合函数。
上面的例子,实现了 point-free
,也就是无参数化,除了 blankPaper
,看不到任何其他参数,剥离任何会影响代码阅读的因素。
为了实现无参数化,就需要用柯里化对函数的的参数进行封装。
以 drawHat 为例子,它除了有 blankPaper
这个参数外,还会有颜色(color),大小(size)等参数。
const drawHat = (color, size, blankPaper) => {
// some code to draw hot
return blankPaper
}
// drawHat 柯里化版本
// 可以用lodash提供的柯里化方法 _.curry
const drawHat = _.curry((color, size, blankPaper) => {
// some code to draw hot
return blankPaper
})(color, size)
这样 drawHat 就只用接受 blankPaper
这一个参数,实现 drawCat 的无参数化。
函数
在数学中,函数定义为:对于一个输入x,总是能得到唯一的输出y,型为y=f(x)这样的对应关系,叫做函数。 编程中,纯函数也就是指的,严格按照y=f(x)来定义的函数,输出只由输入决定,且对于唯一的输入只有唯一的输出。 最简单的例子:
上面add函数,实现了最简单的+1操作,返回值由输入值x决定,且只有唯一的返回值。此时add函数就叫做纯函数。 什么是不纯的函数:
add 返回值由外部变量max和输入值x同时决定,当输入值x+1>max时,返回值变成了0,这样返回值与输入值x不是唯一映射关系了,这样的函数就不是纯函数。
柯里化
柯里化可以看作函数的预存储或者预加载:
柯里化后,可以将a2预加载出来,后续只要是要求2加上任何数字,都可以直接调用a2来计算,这里的a2,就是2的预加载函数。