Sjoerd Visscher's weblog
Last Update
4/23/2006; 7:21:05 PM
Tuesday, February 28, 2006
Tail call elimination in Javascript
Via LtU I read about a tail call optimization decorator. Of course I immediately wondered if it was possible in JavaScript, and it is:
Function.prototype.tailCallOptimized = function()
{
var g = this;
return function()
{
for (var caller = arguments.callee.caller; caller; caller = caller.caller)
if (caller == arguments.callee)
throw {tailCallArgs: arguments, tailCallThis: this};
var args = arguments;
var me = this;
while (true)
{
try
{
return g.apply(me, args);
}
catch(e)
{
if (!e.tailCallArgs)
throw e;
args = e.tailCallArgs;
me = e.tailCallThis;
}
}
};
}
It improves somewhat on the Python example. It allows mutual recursion and recursive methods:
Number.prototype.isEven = function()
{
return this == 0 ? true : (this - 1).isOdd();
}
.tailCallOptimized();
Number.prototype.isOdd = function()
{
return this == 0 ? false : (this - 1).isEven();
};
alert((10001).isEven() ? "even" : "odd");
Note the ‘decorator style’ in Javascript, simply a method call on the function.