簡體   English   中英

我如何在 ES5 中的遞歸匿名函數上應用 TCO(尾調用優化)

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

如果我可以 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;
        }
    }
}

尾調用優化

ES6 提出了對尾調用系統的更改,這是一項引擎優化。 尾調用是指一個函數作為另一個函數中的最后一條語句被調用,如下所示:

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

ECMAScript 6 試圖在嚴格模式下減少某些尾調用的調用堆棧的大小。 通過這種優化,只要滿足以下條件,就不會為尾調用創建新的堆棧幀而是清除並重用當前堆棧幀

  1. 必須開啟嚴格模式。
  2. 尾調用不需要訪問當前堆棧幀中的變量(意味着該函數不是閉包)。
  3. 在尾調用返回后,進行尾調用的函數沒有進一步的工作要做。
  4. 尾調用的結果作為函數值返回。

也許最難避免的情況是使用閉包。 因為閉包可以訪問包含范圍內的變量,所以可能會關閉尾調用優化。 例如:

"use strict";

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

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

利用 TCO 優化:

考慮這個計算階乘的函數:

"use strict";
function factorial(n) {

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

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

為了優化函數,您需要確保在最后一次函數調用之后不會發生乘法運算。

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

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

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

來源: Nicholas Zakas 的一本很棒的書,Understanding ECMAScript 6。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM