js函数式编程——蹦床函数
概述
这是我在学习函数式编程的时候,关于递归,尾递归,相互递归和蹦床函数的一些心得,记下来供以后开发时参考,相信对其他人也有用。
参考资料:JavaScript玩转Clojure大法之 - Trampoline
递归
我们知道,es5是没有尾递归优化的,所以在递归的时候,如果层数太多,就会报“Maximum call stack size exceeded”的错误。就连下面这个及其简单的递归函数都会报“Maximum call stack size exceeded”的错误。
function haha(a) {
if(!a) return a;
return haha(a-1);
}
haha(100); //输出0
haha(12345678); //输出“Maximum call stack size exceeded”
为什么会报“Maximum call stack size exceeded”的错误?我觉得原因是在每次递归调用的时候,会把当前作用域里面的基本类型的值推进栈中,所以一旦递归层数过多,栈就会溢出,所以会报错。
注意:
- js中的栈只会储存基本类型的值,比如:number, string, undefined, null, boolean。
- 为什么在调用下一层递归函数的时候没有释放上一层递归函数的作用域?因为在回来的时候还需要用到里面的变量。
尾递归
怎么优化上面的情况呢?方法是使用尾递归。有尾递归优化的编译器会把尾递归编译成循环的形式,如果没有尾递归优化,那就自己写成循环的形式。如下面的例子所示:
//尾递归函数,返回一个函数调用,并且这个函数调用是自己
function haha(a, b) {
if(b) return b;
return haha(a, a-1);
}
//优化成循环的形式
function yaya(a) {
let b = a;
while(b) {
b = b - 1;
}
}
需要注意的是,看上面尾递归的代码,有一点很重要,就是用一个b变量来存上一次递归的值。这是尾递归常用的方法。另外,其实上面尾递归的代码不需要变量b,但为了便于说明,所以我加上了变量b。
相互递归
但是关于递归还有一种形式,就是相互递归,如下面的代码所示:
function haha1(a) {
if(!a) return a;
return haha2(a-1);
}
function haha2(a) {
if(!a) return a;
return haha1(a-1);
}
haha1(100); //输出0
haha1(12345678); //输出Maximum call stack size exceeded
可以看到,当相互递归层数过多的时候,也会发生栈溢出的情况。
蹦床函数
蹦床函数就是解决上面问题的方法。
首先我们改写上面的相互递归函数:
function haha1(a) {
if(!a) return a;
return function() {
return haha2(a-1);
}
}
function haha2(a) {
if(!a) return a;
return function() {
return haha1(a-1);
}
}
这个改写就是建立一个闭包来封装相互递归的函数,它的好处是由于不是直接的相互递归调用,所以不会把上一次的递归作用域推进栈中,而是把封装函数储存在堆里面,利用堆这个容量更大但读取时间更慢的储存形式来替代栈这个容量小但读取时间快的储存形式,用时间来换取空间。
我们尝试使用一下上面的函数:
haha1(3)(); //输出一个函数
haha1(3)()()(); //输出0
通过上面的示例可以看到,如果参数不是3而是很大的一个数字的时候,我们就需要写很多个括号来实现调用很多次。为了简便,我们可以把这种调用形式写成函数,这就是蹦床函数。如下所示:
function trampoline(func, a) {
let result = func.call(func, a);
while(typeof result === 'function') {
result = result();
}
return result;
}
基本原理是一直调用,直到返回值不是一个函数为止。
最后来使用蹦床函数:
trampoline(haha1, 12345678); //过一会儿就输出0
由于储存在堆中,所以耗时较长,过了一会儿才会输出0,但是并没有报栈溢出的错误。
js函数式编程——蹦床函数的更多相关文章
- Python进阶之函数式编程(把函数作为参数)
什么是函数式编程? 什么是函数式编程? 函数:function 函数式:functional,一种编程范式 函数式编程是一种抽象计算的编程模式 函数≠函数式,比如:计算≠计算机 在计算机当中,计算机硬 ...
- js函数式编程(一)-纯函数
我将写的第一个主题是js的函数式编程,这一系列都是mostly adequate guide这本书的读书总结.原书在gitbook上,有中文版.由于原作者性格活泼,书中夹杂很多俚语,并且行文洒脱.中文 ...
- js函数式编程术语总结 - 持续更新
参考文档1 参考文档2 函数式编程术语 高阶函数 Higher-Order Functions 以函数为参数的函数 返回一个函数的函数 函数的元 Arity 比如,一个带有两个参数的函数被称为二元函数 ...
- js函数式编程(二)-柯里化
这节开始讲的例子都使用简单的TS来写,尽量做到和es6差别不大,正文如下 我们在编程中必然需要用到一些变量存储数据,供今后其他地方调用.而函数式编程有一个要领就是最好不要依赖外部变量(当然允许通过参数 ...
- JS函数式编程 - 概念
最近在看Typescript,顺便看了一些函数式编程,然后半个国庆假期就没有了.做个笔记,分几个部分写吧. 最开始接触函数式编程的时候,第一个接触的概念就是高阶函数,和柯里化.咋一看,这不就是长期用来 ...
- js函数式编程
最近在看朴灵的<深入浅出nodejs>其中讲到函数式编程.理解记录下 高阶函数 比较常见,即将函数作为参数,或是将函数作为返回值得函数. 如ECMAScript5中提供的一些数组方法 fo ...
- 1.python函数式编程-map函数
编程方法论 面向过程 函数式 面向对象 面向过程 将编程过程拆分成多个步骤,在函数中按照每个步骤进行编程: 函数式编程 编程语言定义的函数+数学意义的函数 1.不可变,不用变量保存状态,不修改变量: ...
- day16-python之函数式编程匿名函数
1.复习 #!/usr/bin/env python # -*- coding:utf-8 -*- name = 'alex' #name=‘lhf’ def change_name(): name= ...
- [Python3] 036 函数式编程 返回函数
目录 函数式编程 之 返回函数 1. 引子 2. 闭包 closure 函数式编程 之 返回函数 函数可以返回具体的值 也可以返回一个函数作为结果 1. 引子 1.1 定义一个普通函数 >> ...
随机推荐
- java.util.Stack类中的peek()方法
java.util.stack类中常用的几个方法:isEmpty(),add(),remove(),contains()等各种方法都不难,但需要注意的是peek()这个方法. peek()查看栈顶的对 ...
- 吴裕雄 python深度学习与实践(8)
import cv2 import numpy as np img = cv2.imread("G:\\MyLearning\\TensorFlow_deep_learn\\data\\le ...
- svg矢量图
svg简介 Scalable Vector Graphics 可缩放矢量图形 SVG 图像在放大或改变尺寸的情况下其图形质量不会有所损失 svg知识点 svg如何绘图 svg和cnavas区别 svg ...
- 洛谷P1169 棋盘制作(悬线法)
题目链接:https://www.luogu.org/problemnew/show/P1169 #include<bits/stdc++.h> #define fi first #def ...
- VueJs学习笔记
在cmd下,进入目录之后 cd 到项目目录下 1 安装node cnpm install 2 启动或者调试 cnpm start (或是npm run dev) 3 上线: npm run b ...
- nginx命令启动及选项
[root@ke]# nginx -h #this help [root@ke]# nginx -t #检查配置文件的语法 [root@ke]# nginx -T #检查配置文件的语法并输出 [ ...
- 【Python深入】Python中继承object和不继承object的区别
python中定义class的时候,有object和没有object的不同?例如: class Solution(object): class Solution(): 这俩的区别在于—————— 在p ...
- VS打开SSAS或SSIS报错的解决办法
---------------------------Microsoft Visual Studio---------------------------无法加载类型为“Microsoft.Analy ...
- 什么是XML?
XML被设计用来传输和存储数据. HTML被设计用来显示数据. 什么是XML? XML指可扩展标记语言(EXtensible Markup Language) XML是一种标记语言,很类似HTML X ...
- php 安装gzip
https://jingyan.baidu.com/article/636f38bb3e538ad6b84610e6.html http://w3cgeek.com/configure-error-p ...