个人理解就是将函数作为参数的嵌套函数编写方式,这样写的好处是逻辑会变的很清晰。
从书从直观的感受就是将一个大函数分解为多个函数共同处理的方式,目的是为了减少函数参数的数量,快速封装函数。例:
int pow(int i, int j);
int square(int i)
{
return pow(i, 2);
}
在函数式编程的大环境下,代码块是可以并发执行的,但有时候不需要并发执行,甚至于有时候只需要并发程序中的一个或者两个执行就行了,那么为了不浪费那么多的资源,在函数式编程中程序不需要顺序执行,只有等函数需要调用并发程序的时候再去运行该程序,这样的函数执行方式叫做惰性求值。
因为函数在有需求的情况下才会被调用的原因,所以存在着很多优化的方式和可能,比如在代码执行顺序上作出调整,去掉重复的运算单元
unless(stock.isEuropean()) {
sendToSEC(stock);
}
void unless(boolean condition, List code) {
if(!condition)
code;
}
这里的控制结构可以理解为js里的回调函数,参数中的函数不会立即执行,需要在代码中执行时才会运行。
如果涉及到键盘或者其他输入交互时,惰性求值的弊端就出现了,因无法保证程序能够顺序执行代码。
为了保证程序的函数式执行,又要保证键盘等输入的可控性,所以引入了Continuation指令式编程
Continuation
通常讲函数一定需要将返回值返回给调用者,但是Continuation的引入,函数可以不把函数值返回给调用者,而是允许返回给程序中的任意代码,简单举例如下
//正常写法
int i = add(5, 10);
int j = square(i);
//cps写法
int j = add(5, 10, square);
使用cps(Continuation Pass Style)写法时,在add中多一个参数,这保证必须将计算的结果传入square中。因为在这个编写过程中具有依赖关系了。
匹配模式主要适应的场景是在有很多判断分支,或者实现复杂的嵌套语句时,匹配模式会将复杂的分支或者嵌套更好的拆分多个新函数
先上例子,我将c的程序用js重新写了一下:
function pow(a,b){
return a*b
}
function makePowerFn(power) {
function powerFn( base){
return pow(base,power)
}
return powerFn
}
var square = makePowerFn(2);
console.log(square(3))//6
这里使用的maPowerFn传入参数2时,square函数返回了另一个函数,我们直接调用square函数,便可以得到想要的结果,但问题出现:power传的参数不在powerFn函数的域内,因为makePowerFn已经返回结果了,所以栈也就不存在了。
那么suqare是如何工作的?这个时候需要语言通过某种方式支持继续存储power的值,以便square后面继续使用。那么如果再定义一个函数,cube,用来计算立方,又应该怎么做呢?那么运行中的程序就必须存储两份power的值,提供给makePowerFn生成的两个函数分别使用。这种保存变量值的方法就叫做closure。closure不仅仅保存宿主函数的参数值,还可以用在下例的用法中:
var makeIncrement = () => {
var i = 0
return increment = () =>{
return ++i
}
}
var demo1 = makeIncrement()
var demo2 = makeIncrement()
console.log(demo1(),demo1(),demo1())//1,2,3
console.log(demo2(),demo2(),demo2())//1,2,3
程序运行不仅会存储i的值,以便后续程序访问,也会个i做无限个拷贝