babel-plugin-proper-tail-calls
v1.0.2
Published
A Babel plugin that optimizes tail recursion
Downloads
33
Maintainers
Readme
Proper Tail Calls in JavaScript
Proper tail calls are recursive function calls that do not need to allocate extra stack space proportional to recursion depth. They are a part of the ECMAScript 6 standard but are currently only supported in Safari. This plugin implements proper tail calls through a technique called function trampolining. Using the proper-tail-calls plugin, a program could make an unbounded number of consecutive tail calls without unboundedly growing the stack.
Example
function factorial(num, accumulated = 1) {
if (num <= 1) {
return accumulated;
} else {
return factorial(num - 1, num * accumulated); // proper tail position
}
}
factorial(10)
//=> 3628800
factorial(32687)
//=> RangeError: Maximum call stack size exceeded
const { code } = babel.transform(factorial.toString(), {
plugins: ["proper-tail-calls"]
})
factorial = Function(`${code} return factorial`)()
factorial(32687)
//=> InfinityHow It Works
Recursive calls that are in a proper tail position will be trampolined. Instead of recursing directly, the recursive call is deferred and a wrapper function is returned.
The factorial example above transpiles to:
var factorial = _trampoline(function factorial(num, accumulated = 1) {
if (num <= 1) {
return accumulated;
} else {
return () => {
return factorial(num - 1, num * accumulated);
}
}
})
function _trampoline(fn) {
return function trampolined(...args) {
let result = fn(...args);
while (typeof result === 'function') {
result = result();
}
return result;
};
}Installation
$ npm install --save-dev babel-plugin-proper-tail-callsUsage
Add the following line to your .babelrc file:
{
"plugins": ["proper-tail-calls"]
}babel --plugins proper-tail-calls script.jsVia Node API
require("@babel/core").transform("code", {
plugins: ["proper-tail-calls"]
});