w3future.com

Sjoerd Visscher's weblog

Last Update

4/23/2006; 7:21:05 PM

Try XHTML 2.0
Src XHTML 2.0
RDF Metadata


Site Colors

Syn Atom 1.0
Syn RSS 0.91
Syn Subscribe

CC Licensed
Geo URL
With Radio

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.