函数式编程术语
高阶函数 Higher-Order Functions
以函数为参数的函数
返回一个函数的函数
函数的元 Arity
比如,一个带有两个参数的函数被称为二元函数
惰性求值 Lazy evaluation
是一种按需求值机制,它会延迟对表达式的求值,直到其需要为止
// 设置一个随机数,需要时,才会计算,每次计算都是一个不同的值
const rand = function*() {
while (1 < 2) {
yield Math.random()
}
}
const randIter = rand()
randIter.next() // 每个执行都给出一个随机值,表达式按需求值。
偏函数 Partial Application
即【降元】,将一个 n 元函数转换成一个 n - x 元函数
或者这样理解,通过对【复杂的函数】填充一部分数据来构成一个【简单的函数】
柯里化就是通过偏应用函数来实现
function add(a, b,c) {
return a + b+c;
}
//也可以
var addOne = add.bind(null, 1,2);
console.log(addOne(2));
//也可以
var addTwo = add.bind(null, 1);
console.log(addTwo(3,4));
柯里化 Currying
将一个多参数函数转换成多个单参数函数
也就是将一个 n 元函数转换成 n 个一元函数
const sum = (a, b) => a + b
const curriedSum = (a) => (b) => a + b
curriedSum(40)(2) // 42.
const add2 = curriedSum(2) // (b) => 2 + b
add2(10) // 12
自动柯里化 Auto Currying
将多个参数的函数转换为单参数的函数
如果,给定的参数数量少于正确的参数,则返回一个函数,该函数将获得其余的参数
如果,函数得到正确数量的参数时,它就会被求值
示例,lodash 和 Ramda 都有一个 curry 函数,但 underscore 没有
const add = (x, y) => x + y
const curriedAdd = _.curry(add)
curriedAdd(1, 2) // 3
curriedAdd(1) // (y) => 1 + y
curriedAdd(1)(2) // 3
compose 组合函数
概念:它将需要嵌套执行的函数平铺。嵌套执行指的是,一个函数的返回值将作为另一个函数的参数
作用:实现函数式编程中的 pointfree 风格(无参数),使我们专注于【转换】而不是【数据】
实现:接收多个函数作为参数,从右到左,一个函数的输入为另一个函数的输出
意义:编程更精练、算法更清晰、无参数干扰
威力:==【任意组合】==
缺点:不能直观的看到参数
示例
var compose = function(fun1,fun2){
return function(val){
return fun1(fun2(val));
}
}
var add = function(val){
return val + "111";
}
var upperCase = function(val){
return val.toUpperCase();
}
var double = function(val){
return val += val;
}
// 无限组合,才是compose的威力所在
var upperCaseThenAdd = compose(add,upperCase);
var doubleThenAdd = compose(double,add);
var addThenAdd = compose(add,add);
var addThenAddThenUpperCase = compose(upperCase,addThenAdd);//注意这个函数,以组合函数addThenAdd作为其参数,很强大,有没有!
console.log(upperCaseThenAdd("china"));//CHINA111
console.log(doubleThenAdd("china"));//china111china111
console.log(addThenAdd("china"));//china111111
console.log(addThenAddThenUpperCase("china"));//CHINA111111
//改进compose,支持2个以上参数
var compose1 = function(){
var args = arguments;
return function(initVal){
var val = initVal;
for(key in args){
val = args[key](val);
}
return val;
}
}
var doubleThenUpperCaseThenAddThenAdd = compose1(double,upperCase,add,add);
console.log(doubleThenUpperCaseThenAddThenAdd("china"));//CHINACHINA111111
Continuation
概念:在一个程序执行的任意时刻,尚未执行的代码称为 Continuation
作用:异步请求回调、异步监听回调等
示例
//continueFun函数就称为一个Continuation
var addOneAndContinue = function(val,continueFun){
var val = val + 1;
return continueFun(val);
}
var mutiply = function(val){
return val * 5;
}
console.log(addOneAndContinue(100,mutiply));//505
纯函数 Purity
输出仅由输入决定,不依赖也不修改外部状态,即不产生副作用
副作用 Side effects
如果函数与外部可变状态进行交互,则它是有副作用的
幂等性 Idempotent
数学中的幂等性
foo(x) 将产生与 foo(foo(x))、foo(foo(foo(x))) 等相同的输出
[二元运算],它需要三个元素:二元运算符以及该运算符作用的两个变量。如四则运算的加、减、乘、除均属于二元运算。乘法下唯一两个幂等实数为0和1
[一元运算],例如 ++ ,正+,负-。比如[高斯符号],它是一个数学符号,形式为方括号[x],表示不大于x的最大整数,高斯符号是幂等的
接口的幂等性
对接口而言,幂等性实际上就是接口可重复调用,在调用方多次调用的情况下,接口最终得到的结果是一致的。比如,在App中下订单的时候,点击确认之后,没反应,就又点击了几次。在这种情况下,如果无法保证该接口的幂等性,那么将会出现重复下单问题
[http方法的幂等],指的是同样的请求被执行一次与连续执行多次的效果是一样的,服务器的状态也是一样的(注意,只是服务器状态,和服务器返回状态无关)
举例
GET /pageX HTTP/1.1是幂等的。连续调用多次,客户端接收到的结果都是一样的:
GET /pageX HTTP/1.1
GET /pageX HTTP/1.1
GET /pageX HTTP/1.1
GET /pageX HTTP/1.1
POST /add_row HTTP/1.1不是幂等的。如果调用多次,就会增加多行记录:
POST /add_row HTTP/1.1
POST /add_row HTTP/1.1 -> Adds a 2nd row
POST /add_row HTTP/1.1 -> Adds a 3rd row
DELETE /idX/delete HTTP/1.1是幂等的,即便是不同请求之间接收到的状态码不一样:
DELETE /idX/delete HTTP/1.1 -> Returns 200 if idX exists
DELETE /idX/delete HTTP/1.1 -> Returns 404 as it just got deleted
DELETE /idX/delete HTTP/1.1 -> Returns 404
程序的幂等性
概念:一个函数执行多次皆返回相同的结果
作用:一个函数被调用多次时,保证内部状态的一致性
对比:和纯函数相比,幂等主要强调多次调用,对内部的状态的影响是一样的(但多次调用返回值可能不同)。而纯函数,主要强调相同的输入,多次调用,输出也相同且无副作用。==纯函数一定是幂等的==
意义:在任何可能的情况下通过幂等的操作限制副作用要比不做限制的更新要好得多。确保操作是幂等的,可避免意外的发生 郑州妇科医院:https://yyk.familydoctor.com.cn/21206/郑州人流医院×××:https://yyk.familydoctor.com.cn/21206/郑州看妇科那家好:https://yyk.familydoctor.com.cn/21206/郑州同济妇科医院:https://yyk.familydoctor.com.cn/21206/