如何在ES5中的递归匿名函数上应用TCO(尾调用优化) [英] How do i apply TCO(Tail Call Optimiztion) on recursive anonymous Function in ES5

查看:141
本文介绍了如何在ES5中的递归匿名函数上应用TCO(尾调用优化)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我可以使用命名的递归函数,那么应该有一种方法可以使用tco匿名递归函数。如果有办法,请解释下面的操作方法,这是我的递归函数和TCO函数。

If I can tco a named recursive function there should be a way to tco anonymous recursive function.If there is a way please explain how to do this below is my recursive function and TCO function.

function recursive(length, callback) {

    tco((function (i, sum) {
        var args = arguments;
        if (i > length) {
            console.log("break statement");
            callback(sum)
            return sum
        } else {
            return args.callee(i + 1, sum + i)
        }
    }))(0, 0)
}

function tco(f) {
    var value;
    var active = false;
    var accumulated = [];

    return function accumulator() {
        accumulated.push(arguments);

        if (!active) {
            active = true;

            while (accumulated.length) {
                value = f.apply(this, accumulated.shift());
            }

            active = false;

            return value;
        }
    }
}


推荐答案

尾部呼叫优化



ES6建议对尾部呼叫系统进行更改,即引擎优化。尾调用是指函数被调用为另一个函数中的最后一个语句,如下所示:

Tail Call Optimization

ES6 proposes changes to the tail-call system, an engine optimization. A tail-call is when a function is called as the last statement in another function, like this:

function doSomething() {
    return doSomethingElse();   // tail call
}

ECMAScript 6寻求减小调用堆栈的大小某些尾部调用严格模式。通过此优化,而不是为尾调用创建新的堆栈帧,只要满足以下条件,就会清除并重用当前堆栈帧

ECMAScript 6 seeks to reduce the size of the call stack for certain tail calls in strict mode. With this optimization, instead of creating a new stack frame for a tail call, the current stack frame is cleared and reused so long as the following conditions are met:


  1. 必须打开严格模式。

  2. 尾调用不需要访问当前堆栈帧中的变量(意味着函数不是一个闭包)。

  3. 尾部调用返回后,尾部调用函数没有进一步的工作要做。

  4. 尾部调用的结果作为函数值返回。

  1. strict mode must be turned on.
  2. The tail call does not require access to variables in the current stack frame (meaning the function is not a closure).
  3. The function making the tail call has no further work to do after the tail call returns.
  4. The result of the tail call is returned as the function value.




也许最难避免的情况是使用闭包。因为闭包可以访问包含范围中的变量,所以可以关闭尾调用优化。例如:

Perhaps the hardest situation to avoid is in using closures. Because a closure has access to variables in the containing scope, tail call optimization may be turned off. For example:



"use strict";

function doSomething() {
    var num = 1,
        func = () => num;

    // not optimized - function is a closure
    return func();
}



利用TCO优化:



考虑这个计算阶乘的函数:

Harness the TCO optimization:

Consider this function, which computes factorials:

"use strict";
function factorial(n) {

    if (n <= 1) {
        return 1;
    } else {

        // not optimized - must multiply after returning
        return n * factorial(n - 1);
    }
}

为了优化功能,您需要确保在最后一次函数调用之后不会发生乘法。

In order to optimize the function, you need to ensure that the multiplication doesn’t happen after the last function call.

"use strict";
function factorial(n, p = 1) {

    if (n <= 1) {
        return 1 * p;
    } else {
        let result = n * p;

        // optimized
        return factorial(n - 1, result);
    }
}

来源: An 很棒的由Nicholas Zakas撰写,了解ECMAScript 6。

Source: An Awesome book by Nicholas Zakas, Understanding ECMAScript 6.

这篇关于如何在ES5中的递归匿名函数上应用TCO(尾调用优化)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆