JavaScript 函数式编程 - 蹦床,递归优化

Trampoline 解决 Blowing the stack

JavaScript 引擎没有对递归调用优化。因此,当运行下面的代码时:

const evenSteven = (n) => {
  if (n>0) {
    n = n - 1
    return evenSteven(n)
  }
  return 'over';
}

console.log(evenSteven(1000000))

会出现如下错误(blowing the stack):

RangeError: Maximum call stack size exceeded

要解决这个问题我们可以返回一个函数,它包装调用,而不是直接调用。

const evenSteven = (n) => {
  if (n > 0) {
    n = n - 1
    return () => {
      return evenSteven(n)
    }
  }
  return 'over';
}

console.log(evenSteven(0))
// over
console.log(evenSteven(1))
// [Function]
console.log(evenSteven(2))
// [Function]

这样,我们通过不断调用返回的函数就可以解决栈溢出的问题。

并且我们可以通过一个函数自动来进行 扁平化处理

const _ = require('lodash')

const trampoline = (func) => {
  let res = func()
  while (_.isFunction(res)) {
    res = res()
  }
  return res
}

console.log(trampoline(evenSteven(1000000)))
// over

由于调用链的间歇性,使用蹦床增加了递归开销。然而,慢总比栈溢出好。

我们还可以进行一次包装,将蹦床隐藏在内。

const func = (n) => {
  return trampoline(evenSteven(n))
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 14,266评论 0 38
  • 感谢社区中各位的大力支持,译者再次奉上一点点福利:阿里云产品券,享受所有官网优惠,并抽取幸运大奖:点击这里领取 在...
    HetfieldJoe阅读 1,891评论 0 14
  • 1.函数参数的默认值 (1).基本用法 在ES6之前,不能直接为函数的参数指定默认值,只能采用变通的方法。
    赵然228阅读 847评论 0 0
  • 函数参数的默认值 基本用法 在ES6之前,不能直接为函数的参数指定默认值,只能采用变通的方法。 上面代码检查函数l...
    呼呼哥阅读 3,719评论 0 1
  • 明天就要出门上班,所以昨天晚上去外婆家,和外婆外公告别。 到了外婆家,才七点多一点,外婆已经躺进被窝快要睡觉了。我...
    白天没有影子阅读 355评论 0 0

友情链接更多精彩内容