Tail Recursion in NodeJS

So, I recently came across a case where I needed to write code where callback calls itself, etc., and wondered about NodeJS support and the tail of the call, so I found this answer https://stackoverflow.com/a/212616/2/ . saying yup, he maintained.

So, I tried this with this simple code:

"use strict";
function fac(n){
    if(n==1){
        console.trace();
        return 1;
    }
    return n*fac(n-1);
}

fac(5);

Using Node 6.9.2 on Linux x64 and run it as the node tailcall.js --harmony --harmony_tailcalls --use-strict result was:

Trace
    at fac (/home/tailcall.js:4:11)
    at fac (/home/tailcall.js:7:11)
    at fac (/home/tailcall.js:7:11)
    at fac (/home/tailcall.js:7:11)
    at fac (/home/tailcall.js:7:11)
    at Object.<anonymous> (/home/tailcall.js:10:1)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)

Which clearly shows that the column is filled with calls, and tail recursion is not supported, although I use the latest NodeJS.

NodeJS/JavaScript ? , , , , , - , .

+4
3

, , , - , , , .

, , , , , .

, , .

function getPages(baseURL, startParam, endParam, progressCallback) {

    function run(param) {
         request(baseURL + param, function(err, response, body) {
             if (err) return progressCallback(err);
             ++param;
             if (param < endParam) {
                 progressCallback(null, body);
                 // run another iteration
                 // there is no stack buildup with this call
                 run(param);
             } else {
                 // indicate completion of all calls
                 progressCallback(null, null);
             }
         });
    }
    run(startParam);
}

run() , , , , .


, , , , while, Javascript:

function fac(n){
    var total = 1;
    while (n > 1) {
        total *= n--;
    }
    return total;
}

// run demo in snippet
for (var i = 1; i <= 10; i++) {
    console.log(i, fac(i))
}
Hide result
+3

. - , . - , .

n*fac(n-1), fac(n-1). , - n , , .

, 1 :

const fac = (n, result = 1) =>
  n === 1
    ? result
    : fac(n - 1, n * result);

console.log(fac(5)); // 120
Hide result

:

function fac(n, result = 1) {
  // base case
  if (n === 1) {
    return result;
  }

  // compute the next result in the current stack frame
  const next = n * result;

  // propagate this result through tail-recursive calls
  return fac(n - 1, next);
}

stacktrace Chrome Canary:

Correct tail calls in Chrome Canary

+6

, . , :

"use strict";
var fac = (n, r = 1) => n === 1 ? r : (r *= n, fac(n-1,r));
console.log(fac(5));
Hide result
0

Source: https://habr.com/ru/post/1666859/


All Articles