简体   繁体   中英

How do i apply TCO(Tail Call Optimiztion) on recursive anonymous Function in ES5

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;
        }
    }
}

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 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. 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();
}

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);
    }
}

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM