简体   繁体   English

我如何在 ES5 中的递归匿名函数上应用 TCO(尾调用优化)

[英]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.如果我可以 tco 命名递归函数,那么应该有一种方法可以 tco 匿名递归函数。如果有办法请解释如何做到这一点,下面是我的递归函数和 TCO 函数。

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. ES6 提出了对尾调用系统的更改,这是一项引擎优化。 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. ECMAScript 6 试图在严格模式下减少某些尾调用的调用堆栈的大小。 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:利用 TCO 优化:

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.来源: Nicholas Zakas 的一本很棒的书,Understanding ECMAScript 6。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我如何编写一个递归函数,该函数对使用尾调用优化(TCO)的数字数组求和? - How would I write a recursive function that sums an array of numbers that uses tail call optimization (TCO)? ES6类中的递归方法是否利用了TCO(尾调用优化)? - Do recursive methods in ES6 classes take advantage of TCO (Tail Call Optimization)? 在Javascript ES5和ES6中,如何严格影响此关键字在Function对象的调用和应用方法的上下文中 - How does use strict impact this keyword in the context of call and apply method of a Function object in Javascript ES5 and ES6 如何执行与ES5和ES6兼容的导出? - How do I perform an export that is compatible with ES5 and ES6? 如何使用ES5扩展ES6类? - How do I extend an ES6 class with ES5? 如何创建包含异步调用的 Javascript (es5) 构造函数 function - How to create a Javascript (es5) constructor function containing an asynchronous call 是否有任何 JavaScript 引擎尾调用 (TCO) 优化? - Are any JavaScript engines tail call (TCO) optimized? 尾调用优化 (TCO) 在 Safari 中不起作用 - Tail call optimization (TCO) not working in Safari 在ES5 /严格模式下如何启用正确的尾声? - How are proper tail calls enabled in ES5/strict mode? 尾调用优化递归函数 - Tail Call Optimizing recursive function
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM