【问题标题】:Understanding trampoline optimisation for recursive functions了解递归函数的蹦床优化
【发布时间】:2016-02-10 21:25:40
【问题描述】:

我有以下蹦床实现:

function trampoline(f) {
    while (f && f instanceof Function) {

        f = f.apply(f.context, f.args);

    }
    return f;
}

它的工作原理也是如此,例如阶乘:

function factorial(n) {
    function recur(n, acc) {
        if (n == 0) {
            return acc;
        } else {
            return recur.bind(null, n-1, n*acc);
        }
    }
    return trampoline(recur.bind(null, n, 1));
}

问题是我不明白f.contextf.args 是如何作为参数传入的,例如,当我尝试访问和console.log他们。然后记录 undefined 值。

这个传递函数参数的特定实现的机制是什么?

【问题讨论】:

  • 你能澄清一下使用蹦床与仅仅调用“vanilla”函数相比有什么优势吗?
  • Javascript 默认不优化尾递归,因此很容易超过堆栈限制和耗尽性能。
  • 您的代码似乎运行良好,您能澄清一下问题吗?
  • 问题如前所述,了解如何将 f.context 和 f.args 作为递归参数以及函数如何访问它们。当您尝试在蹦床期间记录它们时,它们会显示未定义。

标签: javascript recursion functional-programming


【解决方案1】:

如您所见here,函数对象没有称为argscontext 的属性,这就是它们在控制台日志中显示为undefined 的原因。在函数本身内部,您可以在 argumentsthis 对象中访问这些值,但在绑定函数(或未绑定函数)中从外部看不到它们

您的代码有效的原因是,如果函数与参数绑定,则会附加 apply 参数。当你bind一个函数时,你只能绑定上下文(this)或者上下文和参数。如果你绑定了上下文和参数,当你applycall那个函数时,你传入的参数会被追加到参数列表的末尾。在您的特定情况下,您正在做...

f = f.apply(undefined, undefined);

... f 的结果参数将是:

[...parametersWhenTheFunctionWasBound, undefined, undefined]

【讨论】:

  • 谢谢。我知道没有这样的属性,因此这个问题。所以它也可以是 null 或 undefined 或者一个普通的函数调用,因为绑定只是延迟执行作为准部分应用程序尝试。
  • 参数数组不会被忽略,而是附加到绑定列表中。
猜你喜欢
  • 1970-01-01
  • 2021-06-01
  • 1970-01-01
  • 2018-11-02
  • 2016-03-24
  • 1970-01-01
  • 2011-12-27
  • 1970-01-01
  • 2020-10-03
相关资源
最近更新 更多